This is a notebook created to document a generic Trade Engine for backtesting and paper trading. It includes a review of the architecture, the type of backtests supported, and a library of documented examples to demonstrate the functionality.
This notebook is for demonstration only, the supporting libraries are not yet available for download. The entire environment, database, and this Jupyter Notebook are available via Docker Compose YML file, all that is required for executing is a local Docker environment. The Git Hub Project with instructions to setup and execute this notebook in a docker container are defined at: https://github.com/zambranag777/Trade_Engine_Demo
This notebook, HTML version, and all the backtest examples results were saved to Excel, and can be retrieved from github at:
Zip file with all results save to Excel: https://github.com/zambranag777/Research_Projects/blob/6ad1eb5684cfb9f08150057a6b050239d6456cec/trade_engine_backtest_examples_results_saved_to_excel.zip
Latest version of this Jupyter Notebok: https://github.com/zambranag777/Research_Projects/blob/6ad1eb5684cfb9f08150057a6b050239d6456cec/TradeEngine_Demo.ipynb
Latest version of this Jupyter Notebok in HTML format: https://github.com/zambranag777/Research_Projects/blob/6ad1eb5684cfb9f08150057a6b050239d6456cec/TradeEngine_Demo.html
The Jupyter Notebook should be opened in Jupyter, it will maintain the organization layout, graphics, and table of contents. All backtest results are saved directly on the notebook, but persisted to distinct Excel files for easier review and analysis.
Feedback is appreciated, please email me at: zambranag@yahoo.com
Gustavo
%load_ext pyinstrument
import os
print( os.environ['PYTHONPATH'] )
%reload_ext autoreload
%autoreload 2
# Python ≥3.6 is required
import sys
assert sys.version_info >= (3, 6)
# Common imports
import numpy as np
import os
import pandas as pd
import yfinance as yf
import feather
import tables
import ta
import socket
from datetime import datetime
# Increaset TF threads for docker containers
import tensorflow as tf
tf.config.threading.set_inter_op_parallelism_threads(44)
tf.config.threading.set_intra_op_parallelism_threads(44)
# Ignore useless warnings (see SciPy issue #5998)
import warnings
warnings.filterwarnings(action="ignore", message="^internal gelsd")
warnings.filterwarnings("ignore", category=RuntimeWarning)
import sqlalchemy
print(sqlalchemy.__version__)
from sqlalchemy.orm import with_polymorphic
# ignore lazy loading warnings
from sqlalchemy import exc as sa_exc
with warnings.catch_warnings():
warnings.simplefilter("ignore", category = sa_exc.SAWarning)
from trade_engine.persist.DBLayer import DBLayer
from trade_engine.persist.DBSchema import DBSchema
import logging
from logging.config import fileConfig
fileConfig('../log/logging.ini')
logging.basicConfig(level=logging.WARN)
logging.getLogger().setLevel(logging.WARN)
# ***Un-comment the code below, and replace with your key or another configuration method
# *** per the quandl link above
#import quandl
#quandl.ApiConfig.api_key = 'typeyourkeyhere'
myDBLayer = DBLayer()
# ***
# *** Connect String for SQL Lite db in memory
# ***
# sqliteConnString = 'sqlite:///:memory:'
# myDBLayer.connect( connString = sqliteConnString )
# ***
# *** Connect String for SQL Lite db file
# ***
# dbTradeEngTestPath = '/Users/gustavozambrana/Google Drive/Python/Projects/Trade_Engine/db/dbTradeEngTest.db'
# ConnString = 'sqlite:///' + dbTradeEngTestPath
# ***
# *** Postgres DB
# ***
ConnString = 'postgresql+pg8000://postgres:postgres@localhost:7777/trade_engine_dev_db'
#ConnString = 'postgresql+pg8000://postgres:postgres@172.17.0.1:7778/trade_engine_demo_db'
# *** Connect to DB, Create DB Schema if not already created, and acquired a DB session
myDBLayer.connect( connString = ConnString )
DBSchema.createDBSchema()
session = DBLayer.getSession()
DBSchema.dropAll()
The main features of the trade engine are:
Performs a backtest for a single trade strategy or a portfolio of trade strategies
Support different kinds of backtests and optimizations of hyper-parameters per trade strategy
Analyzed out-of-sample performance for trade strategies and/or portfolio
Support Technical Analysis Models, as well as AI Based Models to model all trade actions in a trade, that is:
Enter, Exit, Position Sizing, Stop-Loss, Trail-Stop-Loss, etc.
Technical Analysis Models are models that:
AI Based Models are any models that:
Support ensemble models for any trade action in a Trade Strategy, i.e.:
Support mixing Technical Analysis and AI Based Models in ensembles of any trade action
Support persisting all information to execute a backtest in a Relational Database, as well as the results
Setup the architecture to enable distributed cloud execution of backtests
The following are the logical components to define a backtest:
Building and Executing any type of backtest consist of the following steps:
There are different types of backtest supported, the following is a list of the different backtests types and their objectives:
**1. Backtest**
**2. WFA Backtest**
**3. Sliding Window WFA Backtest**
**4. Grid-Search Backtest**
**5. Production-Sim Backtest**
For each trade strategy in a **Backtest or WFA-Backtest** metadata and performance metrics are generated.
Parameter Description
----------------------- --------------------------------------------------------------------
0 ta_reg_item_name Trade Strategy Name
1 ta_reg_item_id Database ID if persisted
2 is_portfolio Indicates if entry correspond to Portfolio summary or T.S.
3 trade_asset Trade Asset associated with Trade Strategy
4 model_type [ Static or Dynamic ], Static ties T.S. to one Trade Asset
5 order_type Simulation for submitting a trade, valid options:
[Market, Stop-Loss, Trail-Stop-Loss, Stop-Loss & Trail-Stop-Loss ]
6 trade_on_etf If underlying trade corresponds to a leverage ETF for the Trade Asset
7 enter_model_unique_name Unique name for enter action model across all Trade Strategies in
the portfolio. For example:
[ ts_sma_1, ts_sma_2 ] correspond to two different SMA T.S.
in the portfolio, configured with different parameters for
modeling enter signals
8 enter_ensemble_model Yes = Ensemble Enter Model, No = Individual enter model
9 enter_num_models Number of enter models in the trade strategy
10 enter_model Enter action model, that is: SMA, MACD, LSTM, GRU, etc. or
composite if an ensemble enter trade strategy in place
11 enter_model_type Type of model, either TA (Technical Analysis signal based) or
AI (Artificial Intellgence based, either ML or DL)
12 enter_models List of all enter models in the trade strategy, if non-ensemble,
this list has only one item, matching the enter_model param
13 exit_model_unique_name Unique name for exit action model across all Trade Strategies in
the portfolio.
14 exit_ensemble_model Yes = Ensemble Exit Model, No = Individual exit model
15 exit_num_models Number of exit models in the trade strategy
16 exit_model Exit action model, that is: SMA, MACD, LSTM, GRU, etc. or
composite if an ensemble exit trade strategy in place
17 exit_model_type Type of model, either TA (Technical Analysis signal based) or
AI (Artificial Intellgence based, either ML or DL)
18 exit_models List of all exit models in the trade strategy, if non-ensemble,
this list has only one item, matching the exit_model param
19 stop_model_unique_name Unique name for stop action model across all Trade Strategies in
the portfolio. For example:
[ ts_stop_1, ts_stop_2 ] correspond to two stop action models
20 stop_ensemble_model Yes = Ensemble Stop Model, No = Individual stop model
21 stop_num_models Number of stop models in the trade strategy
22 stop_model Stop action model, that is: ATR, AI_ATR, etc. or
composite if an ensemble stop trade strategy in place
23 stop_model_type Type of model, either TA (Technical Analysis signal based) or
AI (Artificial Intellgence based, either ML or DL)
24 stop_models List of all stop models in the trade strategy, if non-ensemble,
this list has only one item, matching the stop_model param
25 test_period_len_days For Trade Strategies with at least one AI action model, the
duration of the testing period measured in days.
This corresponds to the backtest date range.
26 tr_period_len_days For Trade Strategies with at least one AI action model, the
duration of the training period measured in days.
27 val_period_len_days For Trade Strategies with at least one AI action model, the
duration of the validation period measured in days.
- Generated by Python QuantStats package ( https://github.com/ranaroussi/quantstats )
- Refer to their documentation for description
1 index
2 Start Period
3 End Period
4 Risk-Free Rate
5 Time in Market
6 Cumulative Return
7 CAGR%
8 Sharpe
9 Sortino
10 Sortino/√2
11 Max Drawdown
12 Longest DD Days
13 Volatility (ann.)
14 Calmar
15 Skew
16 Kurtosis
17 Expected Daily %
18 Expected Monthly %
19 Expected Yearly %
20 Kelly Criterion
21 Risk of Ruin
22 Daily Value-at-Risk
23 Expected Shortfall (cVaR)
24 Gain/Pain Ratio
25 Gain/Pain (1M)
26 Payoff Ratio
27 Profit Factor
28 Common Sense Ratio
29 CPC Index
30 Tail Ratio
31 Outlier Win Ratio
32 Outlier Loss Ratio
33 MTD
34 3M
35 6M
36 YTD
37 1Y
38 3Y (ann.)
39 5Y (ann.)
40 10Y (ann.)
41 All-time (ann.)
42 Best Day
43 Worst Day
44 Best Month
45 Worst Month
46 Best Year
47 Worst Year
48 Avg. Drawdown
49 Avg. Drawdown Days
50 Recovery Factor
51 Ulcer Index
52 Avg. Up Month
53 Avg. Down Month
54 Win Days %
55 Win Month %
56 Win Quarter %
57 Win Year %
Parameter Description
----------------------- -----------------------------------------------------------------
0 ta_reg_item_name
1 ta_reg_item_id
2 tr_num
3 tr_id
4 broker_id
5 trade_asset
6 trade_funds_start
7 trade_funds_end
8 trade_return_end
9 trade_type
10 enter_trade_next_open_period
11 trade_clerance_percent
12 trade_on_etf
13 trade_completed
14 trade_status
15 trade_status_msg
16 order_type
17 trade_entered_executed_price
18 trade_exited_executed_price
19 num_shares
20 trade_entered_date
21 trade_close_date
22 transaction_fee
23 transaction_tax
24 total_transaction_cost
25 stop_loss_per
26 trail_stop_loss_per
27 trade_high_price_at_exit
28 trade_low_price_at_exit
29 trade_high_price_prev_period
30 trade_low_price_prev_period
31 close_stock_price_for_trade_exit_date
32 high_stock_price_for_trade_exit_date
33 low_stock_price_for_trade_exit_date
34 open_stock_price_for_trade_exit_date
35 final_stop_loss_triggered_price
36 final_trail_stop_loss_triggered_price
37 trade_exit_cause
This section gives an overview of the current examples provided, and general instructions
The examples are categorized as follows:
There is a common set of imports for all examples at the beginning that is required to be imported
The examples should be reviewed sequentially, as they get more complex and present more features
as they progress. In addition, some examples refered to explanations and models from previous ones.
Every example has a detail description of the backtest at the start, the trade strategies in the
backtest, the trade actions configured and their supporting models, their Training and Validation Periods (only required if at least one AI model is present in the backtest), Test Period, etc.
Saving and Re-Storing any objects to a database is optional, in some examples is presented, but it is
the same procedure for all examples/objects. In all cases, saving an object, cascades and saves
all children objects, and retreiving an object, retrieves all children objects (lazy loading).
Refer to SQLAlchemy for additional details.
Examples:
**Backtest**
1. Nasdaq ETF - Yahoo Finance Market Data - SMA Trade Strategy
2. Cottons Futures - Quandal Market Data - SMA Trade Strategy
3. Nasdaq ETF - Yahoo Finance Market Data - LSTM Trade Strategy
4. Portfolio A: Buy-and-Hold and SMA Trade Strategies for US Indixes
5. Portfolio B: Buy-and-Hold and AI LSTM based Strategies for US Indixes
6. Portfolio C: Buy-and-Hold and Multiple Configured SMA Trade Strategies for US Indixes
7. Portfolio D: Buy-and-Hold and Multiple Configured LSTM Trade Strategies for US Indixes
8. Portfolio E: Buy-and-Hold and Eleven Distinct Technical Analysis Based Trade Strategies for US Indixes
9. Portfolio F: Buy-and-Hold and Multiple Configured AI Modeled Trade Strategies for US Indixes
10. Portfolio G: All Trade Strategies in Portfolio E and F
11. Portfolio H: Utilized Leveraged ETFs for Trading on The Model Trade-Asset
12. Portfolio I: Monthly Rebalance of Funds in a Portfolio
13. Portfolio J: Trade Strategies with different Market Data Sources (Quandal, YahooFinance, User-Defined DataFrame)
14. Portfolio K: Buy-and-Hold and Multiple Configured SMA Trade Strategies for US Indixes, with Stop Models
15. Portfolio L: Buy-and-Hold and Multiple Configured TA Trade Strategies for US Indixes, with Stop Models
16. Portfolio M: Buy-and-Hold and Multiple Configured AI Trade Strategies for US Indixes, with Stop Models
17. Portfolio N: Buy-and-Hold and Multiple Configured AI Trade Strategies for US Indixes, with AI based Stop Models
**WFA Backtest**
1. WFA-Backtest-1
2. WFA-Backtest-2
3. WFA-Backtest-3
**Slide Window WFA Backtest**
1. SW-WFA-Backtest 1
2. SW-WFA-Backtest 2
3. SW-WFA-Backtest 3
4. SW-WFA-Backtest 4
5. SW-WFA-Backtest 5
**Grid Backtest**
To be added
**Production Sim Backtest**
To be added
**Reports**
1. Create Full Tearsheet Reports
2. Create HTML Tearsheet Reports
**Other**
1. Trade Fee Policy
# *** Imports required for running Trade Strategy examples
from trade_engine.model.TradeStrategyBaseModelPersist import TradeStrategyBaseModelPersist
from trade_engine.model.TradeStrategyModelStatic import TradeStrategyModelStatic
from trade_engine.model.TradeStrategyMarketDataMng import TradeStrategyMarketDataMng
from trade_engine.model.MarketDataPeriod import MarketDataPeriod
from trade_engine.ts_actions.generate.TradeStrategyActionGenerator import TradeStrategyActionGenerator
from trade_engine.ts_actions.generate.TradeAssetRegisterItemGenerator import TradeAssetRegisterItemGenerator
from trade_engine.ts_actions.generate.TradeStrategyConfigData import TradeStrategyConfigData
from trade_engine.investment_manager.TradingAssetInvMngBase import TradingAssetInvMngBase
from trade_engine.registry.TradingAssetExecutionType import TradingAssetExecutionType
from trade_engine.registry.TradingAssetRegisterItem import TradingAssetRegisterItem
from trade_engine.broker.SimBrokerTrading import SimBrokerTrading
from trade_engine.execution.BacktestExecution import BacktestExecution
from trade_engine.dataset_def.DatasetDef import DatasetDef, DatasetType
from trade_engine.dataset_def.FitDatasetsDef import FitDatasetsDef
from trade_engine.reports.BacktestReports import BacktestReports
# *** Additional Imports required for running Portfolio examples
from tradeg.market_data.MarketData import MarketData
from trade_engine.model.TALibPipelineBuilder import TALibPipelineBuilder
from trade_engine.model.TradeStrategyModelPipelineDataMng import TradeStrategyModelPipelineDataMng
from trade_engine.enter_ts.TradeEnterClassicStrategy import TradeEnterClassicStrategy
from trade_engine.exit_ts.TradeExitClassicStrategy import TradeExitClassicStrategy
from trade_engine.model.classic.CacheTradingModel import CacheTradingModel
from trade_engine.model.classic.TradingRulesModel import TradingRulesModel
from trade_engine.model.classic.VotingTradingRulesModel import VotingTradingRulesModel
from trade_engine.exit_ts.TradeExitStack import TradeExitStack
from trade_engine.enter_ts.TradeEnterStack import TradeEnterStack
from trade_engine.investment_manager.PortfolioInvMng import PortfolioInvMng
from trade_engine.investment_manager.PortfolioRebalanceFrequency import PortfolioRebalanceFrequency
from trade_engine.registry.PortfolioRegisterItem import PortfolioRegisterItem
from trade_engine.model.ai.LSTM_Model import LSTM_Model
from trade_engine.model.ai.WaveNet_RNN_AI_TradingModel import WaveNet_RNN_AI_TradingModel
from trade_engine.model.ai.WaveNet_RNN_AI_TradingModel import WaveNet_RNN_AI_Trading_Rules
from trade_engine.model.ai.WaveNet_RNN_AI_PipelineBuilder import WaveNet_RNN_AI_PipelineBuilder
from trade_engine.enter_ts.TradeEnterAIStrategy import TradeEnterAIStrategy
from trade_engine.exit_ts.TradeExitAIStrategy import TradeExitAIStrategy
from trade_engine.ts_actions.policy.TradeEnterSetPolicy import TradeEnterSetPolicy, TradeEnterSetVotingPolicy
from trade_engine.ts_actions.policy.TradeEnterPolicy import TradeEnterPolicy
from trade_engine.ts_actions.policy.TradeExitSetPolicy import TradeExitSetPolicy, TradeExitSetVotingPolicy
from trade_engine.ts_actions.policy.TradeExitPolicy import TradeExitPolicy
# *** Additional Imports required for running WFA Backtest and Slide Win WFA Backtest
from trade_engine.execution.BacktestExecutionWFA import BacktestExecutionWFA, WFASlideWindowPeriod
from trade_engine.execution.BacktestExecutionSlideWindowWFA import BacktestExecutionSlideWindowWFA
from trade_engine.execution.BacktestExecutionSlideWindowWFA import WFASlideWinScenarioFixDatasets
from trade_engine.execution.BacktestExecutionSlideWindowWFA import WFASlideWinScenarioSlidingDatasets
from trade_engine.execution.BacktestExecutionSlideWindowWFA import WFASlideWinScenarioAnchoredSlidingDatasets
# For other examples
from trade_engine.investment_manager.TradeFeePolicy import TradeFeePolicy, TradeFeeType
SMA Trade Strategy for Nasdaq ETF
Description:
1. $2.0M Budget
2. 100% capital invested
Trade Strategies:
1. One trade strategy: Nasdaq using Simple Moving Average(SMA) for entering/exiting a trade
Backtest:
1. Type: regular
2. Test Period:
1. Begin Date = 2001-01-01
2. End Date = 2005-12-31
trade_asset = "^IXIC"
Market Data Manager configured to use yahoo-finance for obtaining market data
The following TradeStrategyMarketDataMng object will do the following:
1. Download market data for:
[ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
2. Used yahoo-finance as the market provider
3. Save the downloaded data in the directory and file specified by the arguments:
1. dirPathMarketData
2. fileNameMarketData
4. It will request the market data provider to get data from "beg_date_str" to "end_date_str"
5. If end_date_str is not defined (as the case below), all data available from the begin date is
requested.
6. Interval is set to "1d", this parameter is market data provider specific, see Yahoo-Finance,
Quandal for what options they support
7. The **Adj Close** column is configured as the default price column
8. Note that even so leveraged ETFs are requested from 2000-01-01 to the present, the data
actually returned for these stock symbols by Yahoo-Finance doesn't start until 2011.
The behavior is market data provider specific
#dirPathMarketData = '/Users/gustavozambrana/Google Drive/Python/Projects/Trade_Engine/Data/US_Market_Indixes'
dirPathMarketData = '../Data/US_Market_Indixes'
supportedTradeAssets = [ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
beg_date_str = "2000-01-01"
end_date_str = None
ts_marketdat_mng = TradeStrategyMarketDataMng(\
marketDataProviderName = "yahoofinance",
supportedTradeAssets = supportedTradeAssets,
stock_price_col_name = "Adj Close",
fileNameMarketData = "US_Indixes_And_ETFs_MrkData",
dirPathMarketData = dirPathMarketData,
beg_date_str = beg_date_str,
end_date_str = end_date_str,
forceCreateMarketData = False,
interval = "1d" )
ts_marketdat_mng.marketDataObj.getDataFrame()
brokerTradingObj = SimBrokerTrading()
tsConfDat = TradeStrategyConfigData()
# SMA JSON Configuration
#
# Model Configuration:
# win_fast : fast moving average
# win_slow : slow moving average
# Signals to enter and exit a trade based on the fast ma crossing the slow ma
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 20, 'win_slow' : 100 } },
} } )
taRegItemGen = TradeAssetRegisterItemGenerator()
ts_registered_obj = taRegItemGen.createSingleTARegItem(
name_ta_reg_item = "Nasdaq ETF Backtest",
# *** Trade Assets & Market Data
trade_asset = trade_asset,
ts_marketdat_mng = ts_marketdat_mng,
dirPathMarketData = dirPathMarketData,
market_data_period = MarketDataPeriod.Day,
# *** Broker
brokerTradingObj = brokerTradingObj,
# *** T.S. Permutations for each of the following sets of models
enter_exit_config_models = tsConfDat,
# *** Investment Manager Params
minPeriodsBetweenTrades = 1,
initInvestment = 2000000.0,
capPercentToInvestPerTrade = 100.0,
minInvestPercent = 5.0,
enter_trade_next_open_period = True,
min_account_balance = 1000.0,
)
print("Number of Enter Models: ", len(ts_registered_obj.getTradeStrategyModel().getTSEnterSetObj().tsEntries) )
ts_registered_obj.getTradeStrategyModel().getTSEnterSetObj().tsEntries[0].ts_model_pipline_mng.\
getAllModelDataPipelineDataForStockSymbol(stockSymbol = "^IXIC" )
tsExecuteEngine = BacktestExecution( \
name = "Backtest for Nasdaq ETF - SMA Trade Strategy",
timePeriod = DatasetDef(datasetType = DatasetType.Testing,
strBegDate = "2001-01-01",
strEndDate = "2005-12-31" ),
trade_asset_registered_item = ts_registered_obj )
tsExecuteEngine.evaluate()
tsExecuteEngine.getSummaryMetrics().to_excel("Nasdaq ETF SMA Model backtest-metrics.xlsx")
tsExecuteEngine.getExecutionMetrics()
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 'Start Period', 'End Period', 'Time in Market ',
'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ]
session.add( tsExecuteEngine )
try :
session.commit()
except Exception as inst:
print(type(inst)) # the exception instance
print(inst)
print(inst.args) # arguments stored in .args
session.rollback() # roll back changes
finally:
print(" done")
SMA Trade Strategy for Cottons Future
Description:
1. $2.0M Budget
2. 100% capital invested
Trade Strategies:
1. One trade strategy: Cotton's Futures using Simple Moving Average(SMA) for entering/exiting a trade
Backtest:
1. Type: regular
2. Test Period:
1. Begin Date = 2002-01-01
2. End Date = 2005-12-31
trade_asset = "CHRIS/ICE_CT1"
Download the following data from Quandal:
CHRIS/ICE_CT1
Where CHRIS is the Quandal Data Provider, and the name after the / is the Futures symbol.
The format of the JSON to download from Quandal is:
{ quandal-path :
[ description of data,
[ columns to extract from the returned Quandal DataFrame ],
{ "Quandal_Column" : "Rename Quandal Column" }
]
}
Note:
1. The nested dictionary to rename the original downloaded Quandal data, it is provided since Quandal does
not have standard output column names.
- Futures data from different data sources might have different returned column names for the same
state, that is "Close" vs. "close", etc.
- For sharing the same market data manager object it is recommended to rename the columns to have
standard names, and match the ones provided by Yahoo Finance
2. Yahoo Finance returns standard equity column names
3. All implemented AI and Technical Models used standard column names (same as Yahoo Finance)
Columns: Adj Close, Close, Open, High, Low, Volume
Index: Datetime
4. In order to use the implemented models the Quandal Market Data or any Custom Market Data must have
similar named columns, or the user can implement his own models and use whatever column names he/she
prefers.
5. In this example, the Quandal data source does not provide all standard column names, only open,
which is re-named to 'Adj Close'. Therefore only some of the built models will be available,
as they required High, Low, such as Bollinger Bands
indexQuantCodeMap = {
"CHRIS/ICE_CT1" : ["Cotton", ["Open", "Volume"], { "Open" : "Adj Close" } ]
}
dirPathMarketDataQuandl = '../Data/TSMarketDat'
beg_date_for_feature_creation = "2000-10-01"
beg_date_str = "2001-01-01"
end_date_str = "2010-12-31"
q_stock_index_list = list ( indexQuantCodeMap.keys() )
ts_marketdat_mng_quandal = TradeStrategyMarketDataMng(\
marketDataProviderName = "quandl",
supportedTradeAssets = q_stock_index_list,
stock_price_col_name = "Adj Close",
fileNameMarketData = "Quandl_Test_1",
dirPathMarketData = dirPathMarketDataQuandl,
beg_date_str = beg_date_for_feature_creation,
end_date_str = end_date_str,
interval = "1d" ,
updateDataPassEndDate = False,
forceCreateMarketData = False,
indexQuantCodeMap = indexQuantCodeMap, # required for quandl market data provider, defined above
# The Quandal provider used does not return Open, High, Low, Close, so map the "Adj Close" column
# to all standard columns in order to utilized some of the models that required that data (ATR, etc.)
create_std_ohlc_cols_dict = { "Open" : "Adj Close", "Low" : "Adj Close",
"High" : "Adj Close", "Close" : "Adj Close" }
)
ts_marketdat_mng_quandal.marketDataObj.getDataFrame()
brokerTradingObj = SimBrokerTrading()
tsConfDat = TradeStrategyConfigData()
# SMA JSON Configuration
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 20, 'win_slow' : 100 } },
} } )
taRegItemGen = TradeAssetRegisterItemGenerator()
ts_registered_obj = taRegItemGen.createSingleTARegItem(
name_ta_reg_item = "Cotton Futures Backtest",
# *** Trade Assets & Market Data
trade_asset = trade_asset,
ts_marketdat_mng = ts_marketdat_mng_quandal,
dirPathMarketData = dirPathMarketData,
market_data_period = MarketDataPeriod.Day,
# *** Broker
brokerTradingObj = brokerTradingObj,
# *** T.S. Permutations for each of the following sets of models
enter_exit_config_models = tsConfDat,
# *** Investment Manager Params
minPeriodsBetweenTrades = 1,
initInvestment = 2000000.0,
capPercentToInvestPerTrade = 100.0,
minInvestPercent = 5.0,
enter_trade_next_open_period = True,
min_account_balance = 1000.0,
)
ts_registered_obj.getTradeStrategyModel().getTSEnterSetObj().tsEntries[0].ts_model_pipline_mng.\
getAllModelDataPipelineDataForStockSymbol(stockSymbol = trade_asset )
tsExecuteEngine = BacktestExecution( \
name = "Backtest for Cottons Futures - SMA Trade Strategy",
timePeriod = DatasetDef(datasetType = DatasetType.Testing,
strBegDate = "2002-01-01",
strEndDate = "2005-12-31" ),
trade_asset_registered_item = ts_registered_obj )
tsExecuteEngine.evaluate()
tsExecuteEngine.getSummaryMetrics().to_excel("Cottons Futures backtest-metrics.xlsx")
tsExecuteEngine.getExecutionMetrics()
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 'Start Period', 'End Period', 'Time in Market ',
'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ]
session.add( tsExecuteEngine )
try :
session.commit()
except Exception as inst:
print(type(inst)) # the exception instance
print(inst)
print(inst.args) # arguments stored in .args
session.rollback() # roll back changes
finally:
print(" done")
LSTM Trade Strategy for Nasdaq ETF
Description:
1. $2.0M Budget
2. 100% capital invested
Trade Strategies:
1. One trade strategy: Nasdaq using a LSTM-Model for entering/exiting a trade
Backtest:
1. Type: regular
2. AI Models Fit Date Ranges
1. Training Period:
1. Begin Date = 2001-01-01
2. End Date = 2005-12-31
2. Validation Period:
1. Begin Date = 2006-01-01
2. End Date = 2007-12-31
4. Test Period:
1. Begin Date = 2008-01-01
2. End Date = 2008-12-31
trade_asset = "^IXIC"
Market Data Manager configured to use yahoo-finance for obtaining market data
The following TradeStrategyMarketDataMng object will do the following:
1. Download market data for:
[ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
2. Used yahoo-finance as the market provider
3. Save the downloaded data in the directory and file specified by the arguments:
1. dirPathMarketData
2. fileNameMarketData
4. It will request the market data provider to get data from "beg_date_str" to "end_date_str"
5. If end_date_str is not defined (as the case below), all data available from the begin date is
requested.
6. Interval is set to "1d", this parameter is market data provider specific, see Yahoo-Finance,
Quandal for what options they support
7. The **Adj Close** column is configured as the default price column
8. Note that even so leveraged ETFs are requested from 2000-01-01 to the present, the data
actually returned for these stock symbols by Yahoo-Finance doesn't start until 2011.
The behavior is market data provider specific
dirPathMarketData = '../Data/US_Market_Indixes'
supportedTradeAssets = [ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
beg_date_str = "2000-01-01"
end_date_str = None
ts_marketdat_mng = TradeStrategyMarketDataMng(\
marketDataProviderName = "yahoofinance",
supportedTradeAssets = supportedTradeAssets,
stock_price_col_name = "Adj Close",
fileNameMarketData = "US_Indixes_And_ETFs_MrkData",
dirPathMarketData = dirPathMarketData,
beg_date_str = beg_date_str,
end_date_str = end_date_str,
forceCreateMarketData = False,
interval = "1d" )
ts_marketdat_mng.marketDataObj.getDataFrame()
brokerTradingObj = SimBrokerTrading()
tsConfDat = TradeStrategyConfigData()
# LSTM JSON Configuration
#
# Model configuration:
# Simple LSTM MOdel with two layers
# n_steps : length of time series
# no_neurons_lay1 : layer 1 neurons
# no_neurons_lay2 : layer 2 neurons
# pred_ahead_periods : Number of prediction points ahead
# epochs : Number of epochs
# ext_trade_dyn : Extend an existent trade dymically based on current period predictions
# re_eval_exit_dyn : Re-evaluate exiting a trade dynamically based on current period predictions
# entry_policy_args :
# lastn_match : Enter a trade if the last n predictions matched
# cross_enter_signal : Enter a trade if the there is a cross-over signal,
# from buy-to-sell, sell-to-buy
# exit_policy_args :
# lastn_match : Exit a trade if the last n predictions matched
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_lstm",
'actions_conf' : { "entry_exit" :
{ 'model' : "lstm",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 3,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
taRegItemGen = TradeAssetRegisterItemGenerator()
ts_registered_obj = taRegItemGen.createSingleTARegItem(
name_ta_reg_item = "Nasdaq ETF -LSTM Model- Backtest",
# *** Trade Assets & Market Data
trade_asset = trade_asset,
ts_marketdat_mng = ts_marketdat_mng,
dirPathMarketData = dirPathMarketData,
market_data_period = MarketDataPeriod.Day,
# *** Broker
brokerTradingObj = brokerTradingObj,
# *** T.S. Permutations for each of the following sets of models
enter_exit_config_models = tsConfDat,
# *** Investment Manager Params
minPeriodsBetweenTrades = 1,
initInvestment = 2000000.0,
capPercentToInvestPerTrade = 100.0,
minInvestPercent = 5.0,
enter_trade_next_open_period = True,
min_account_balance = 1000.0,
)
# Pipeline just normalizes the data for LSTM Model
ts_registered_obj.getTradeStrategyModel().getTSEnterSetObj().tsEntries[0].ts_model_pipline_mng.\
getAllModelDataPipelineDataForStockSymbol(stockSymbol = "^IXIC" )
In Order to backtest a trade strategy or portfolio that has AI models, the following data is required:
Training Date Range
Validation Date Range
Date Ranges are defined with a DatasetDef object, and have the following parameters:
Note:
training_period = DatasetDef(datasetType = DatasetType.Training,
strBegDateAIModels = "2000-07-01",
strBegDate = "2001-01-01",
strEndDate = "2005-12-31" )
validation_period = DatasetDef(datasetType = DatasetType.Validation,
strBegDateAIModels = "2005-07-01",
strBegDate = "2006-01-01",
strEndDate = "2007-12-31" )
testing_period = DatasetDef(datasetType = DatasetType.Testing,
strBegDateAIModels = "2007-07-01",
strBegDate = "2008-01-01",
strEndDate = "2008-12-31" )
fit_datasets = FitDatasetsDef( trainingDataset = training_period,
validationDataset = validation_period )
tsExecuteEngine = BacktestExecution( \
name = "Backtest for Nasdaq-ETF LSTM based Trade Strategy",
timePeriod = testing_period,
fitDatasets = fit_datasets,
trade_asset_registered_item = ts_registered_obj )
tsExecuteEngine.evaluate()
tsExecuteEngine.getSummaryMetrics().to_excel("Nasdaq ETF LSTM Model backtest-metrics.xlsx")
tsExecuteEngine.getExecutionMetrics()
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 'Start Period', 'End Period', 'Time in Market ',
'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ]
session.add( tsExecuteEngine )
try :
session.commit()
except Exception as inst:
print(type(inst)) # the exception instance
print(inst)
print(inst.args) # arguments stored in .args
session.rollback() # roll back changes
finally:
print(" done")
Portfolio A: Long and SMA Trade Strategies for US Indixes
Description:
1. Portfolio with 6 trading strategies
2. $2,000,000/strategy
3. No-Rebalance during the backtest
4. 100% capital invested
5. Portfolio investment using equal weights for each trade strategy
Trade Strategies:
1. Three trade strategies: Nasdaq, S&P 500, and DOW Jones with buy-and-hold
2. Three trade strategies: Nasdaq, S&P 500, and DOW Jones using SMA
Backtest:
1. Type: regular
2. Test Period:
1. Begin Date = 2001-01-01
2. End Date = 2001-12-31
portfolio_trade_assets = [ "^DJI", "^IXIC", "^GSPC" ]
dirPathMarketData = '../Data/US_Market_Indixes'
supportedTradeAssets = [ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
beg_date_str = "2000-01-01"
end_date_str = None
ts_marketdat_mng = TradeStrategyMarketDataMng(\
marketDataProviderName = "yahoofinance",
supportedTradeAssets = supportedTradeAssets,
stock_price_col_name = "Adj Close",
fileNameMarketData = "US_Indixes_And_ETFs_MrkData",
dirPathMarketData = dirPathMarketData,
beg_date_str = beg_date_str,
end_date_str = end_date_str,
forceCreateMarketData = False,
interval = "1d" )
ts_marketdat_mng.marketDataObj.getDataFrame().query('Index == "^DJI" ')
tsConfDat = TradeStrategyConfigData()
# Model Params
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_1",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 10, 'win_slow' : 50 } ,
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 2 } },
},
} )
brokerTradingObj = SimBrokerTrading()
taRegItemGen = TradeAssetRegisterItemGenerator()
portf_registered_obj = taRegItemGen.createTARegItem(
name_ta_reg_item = "Portfolio A",
# *** Trade Assets & Market Data
portfolio_trade_assets = portfolio_trade_assets,
ts_marketdat_mng = ts_marketdat_mng,
dirPathMarketData = dirPathMarketData,
market_data_period = MarketDataPeriod.Day,
# *** Broker
brokerTradingObj = brokerTradingObj,
# *** T.S. Permutations for each of the following sets of models
enter_exit_config_models = tsConfDat,
# *** Investment Manager Params
minPeriodsBetweenTrades = 1,
initInvestmentPerTradeStrategy = 2000000.0,
capPercentToInvestPerTrade = 100.0,
minInvestPercent = 5.0,
enter_trade_next_open_period = True,
min_account_balance = 1000.0,
portfRebalanceFreq = PortfolioRebalanceFrequency.Never,
portfRebalancePeriods = 1
)
session.add( portf_registered_obj )
try :
session.commit()
except Exception as inst:
print(type(inst)) # the exception instance
print(inst.args) # arguments stored in .args
session.rollback() # roll back changes
finally:
print(" done")
session.expunge_all()
del portf_registered_obj
for tsObj in session.query(PortfolioRegisterItem):
print(tsObj.name)
if tsObj.name == "Portfolio A" :
break
portf_registered_obj = tsObj
print(portf_registered_obj.id, portf_registered_obj.name)
tsExecuteEngine = BacktestExecution( \
name = "Backtest for Portfolio A",
timePeriod = DatasetDef(datasetType = DatasetType.Testing,
strBegDate = "2001-01-01",
strEndDate = "2001-12-31" ),
trade_asset_registered_item = portf_registered_obj )
tsExecuteEngine.evaluate()
tsExecuteEngine.getSummaryMetrics().to_excel("Portfolio-A backtest-metrics.xlsx")
tsExecuteEngine.getExecutionMetrics()
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 'Start Period', 'End Period', 'Time in Market ',
'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ]
session.add( tsExecuteEngine )
try :
session.commit()
except Exception as inst:
print(type(inst)) # the exception instance
print(inst)
print(inst.args) # arguments stored in .args
session.rollback() # roll back changes
finally:
print(" done")
session.expunge_all()
del tsExecuteEngine
for tsObj in session.query(BacktestExecution):
print(tsObj.name)
if tsObj.name == "Backtest for SMA based Trade Strategies" :
break
tsExecuteEngine = tsObj
print(tsExecuteEngine.id, tsExecuteEngine.name)
tsExecuteEngine.getExecutionMetrics()
Portfolio B: Long and AI LSTM based Strategies for US Indixes
Description:
1. Portfolio with 6 trading strategies
2. $2,000,000/strategy
3. No-Rebalance during the backtest
4. 100% capital invested
5. Portfolio investment using equal weights for each trade strategy
Trade Strategies:
1. Three trade strategies: Nasdaq, S&P 500, and DOW Jones with buy-and-hold
2. Three trade strategies: Nasdaq, S&P 500, and DOW Jones using LSTM AI Model
Backtest:
1. Type: regular
2. AI Models Fit Date Ranges
1. Training Period:
1. Begin Date = 2001-01-01
2. End Date = 2005-12-31
2. Validation Period:
1. Begin Date = 2006-01-01
2. End Date = 2007-12-31
4. Test Period:
1. Begin Date = 2008-01-01
2. End Date = 2008-12-31
portfolio_trade_assets = [ "^DJI", "^IXIC", "^GSPC" ]
dirPathMarketData = '../Data/US_Market_Indixes'
supportedTradeAssets = [ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
beg_date_str = "2000-01-01"
end_date_str = None
ts_marketdat_mng = TradeStrategyMarketDataMng(\
marketDataProviderName = "yahoofinance",
supportedTradeAssets = supportedTradeAssets,
stock_price_col_name = "Adj Close",
fileNameMarketData = "US_Indixes_And_ETFs_MrkData",
dirPathMarketData = dirPathMarketData,
beg_date_str = beg_date_str,
end_date_str = end_date_str,
forceCreateMarketData = False,
interval = "1d" )
tsConfDat = TradeStrategyConfigData()
# Model Params
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_lstm",
'actions_conf' : { "entry_exit" :
{ 'model' : "lstm",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
brokerTradingObj = SimBrokerTrading()
taRegItemGen = TradeAssetRegisterItemGenerator()
portf_registered_obj = taRegItemGen.createTARegItem(
name_ta_reg_item = "Portfolio B",
# *** Trade Assets & Market Data
portfolio_trade_assets = portfolio_trade_assets,
ts_marketdat_mng = ts_marketdat_mng,
dirPathMarketData = dirPathMarketData,
market_data_period = MarketDataPeriod.Day,
# *** Broker
brokerTradingObj = brokerTradingObj,
# *** T.S. Permutations for each of the following sets of models
enter_exit_config_models = tsConfDat,
# *** Investment Manager Params
minPeriodsBetweenTrades = 1,
initInvestmentPerTradeStrategy = 2000000.0,
capPercentToInvestPerTrade = 100.0,
minInvestPercent = 5.0,
enter_trade_next_open_period = True,
min_account_balance = 1000.0,
portfRebalanceFreq = PortfolioRebalanceFrequency.Never,
portfRebalancePeriods = 1
)
session.add( portf_registered_obj )
try :
session.commit()
except Exception as inst:
print(type(inst)) # the exception instance
print(inst.args) # arguments stored in .args
session.rollback() # roll back changes
finally:
print(" done")
session.expunge_all()
del portf_registered_obj
for tsObj in session.query(PortfolioRegisterItem):
if tsObj.name == "Portfolio B" :
break
portf_registered_obj = tsObj
print(portf_registered_obj.id, portf_registered_obj.name)
training_period = DatasetDef(datasetType = DatasetType.Training,
strBegDateAIModels = "2000-07-01",
strBegDate = "2001-01-01",
strEndDate = "2005-12-31" )
validation_period = DatasetDef(datasetType = DatasetType.Validation,
strBegDateAIModels = "2005-07-01",
strBegDate = "2006-01-01",
strEndDate = "2007-12-31" )
testing_period = DatasetDef(datasetType = DatasetType.Testing,
strBegDateAIModels = "2007-07-01",
strBegDate = "2008-01-01",
strEndDate = "2008-12-31" )
fit_datasets = FitDatasetsDef( trainingDataset = training_period,
validationDataset = validation_period )
tsExecuteEngine = BacktestExecution( \
name = "Backtest for Portfolio B",
timePeriod = testing_period,
fitDatasets = fit_datasets,
trade_asset_registered_item = portf_registered_obj )
tsExecuteEngine.evaluate()
tsExecuteEngine.getSummaryMetrics().to_excel("Portfolio-B backtest-metrics.xlsx")
tsExecuteEngine.getExecutionMetrics()
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 'Start Period', 'End Period', 'Time in Market ',
'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ]
session.add( tsExecuteEngine )
try :
session.commit()
except Exception as inst:
print(type(inst)) # the exception instance
print(inst.args) # arguments stored in .args
session.rollback() # roll back changes
finally:
print(" done")
session.expunge_all()
del tsExecuteEngine
for tsObj in session.query(BacktestExecution):
if tsObj.name == "Backtest for Portfolio B" :
break
tsExecuteEngine = tsObj
print(tsExecuteEngine.id, tsExecuteEngine.name)
tsExecuteEngine.getExecutionMetrics()
Portfolio C: Long and Multiple Configured SMA Trade Strategies for US Indixes
Description:
1. Portfolio with 27 trading strategies
2. $2,000,000/strategy
3. No-Rebalance during the backtest
4. 100% capital invested
5. Portfolio investment using equal weights for each trade strategy
Trade Strategies:
1. Three trade strategies: Nasdaq, S&P 500, and DOW Jones with buy-and-hold
2. 21 trade strategies: Nasdaq, S&P 500, and DOW Jones using following SMA Configuration:
sma-conf fast_mav, slow_mav, enter_if_last_nmatch, enter_if_cross_over_sig, exit_if_last_nmatch
1 20 100 2 True 2
2 10 50 2 True 2
3 10 50 2 True 1
4 15 60 2 True 2
5 15 75 2 True 1
6 7 35 2 True 2
7 7 35 2 True 1
3. Three trade strategies: Nasdaq, S&P 500, and DOW Jones using the following configuration:
- A Composite SMA Trade Strategy based on the the first five SMA Configured trade strategies
above
- The Set Entry cofiguration rules are:
a. Majority Voting (default)
Three of the Five SMA Indicators configured in the set must signaled the same type of
investment decision.
b. Enter a trade if the last n voting decisions are the same, set to 1 (default )
c. Enter a trade if there is cross-over signaled after applying rules a) and b),
set to False (default)
- The Set Exit configuration rules are:
a. Majority Voting (Default)
- Exit a long trade if the percent of SMA Indicators signaling an exit for a long position
is greater that the percent signaling no-exit
- Exit a short trade if the percent of SMA Indicators signaling an exit for a short position
is greater that the percent signaling no-exit
b. Exit a trade if the last n exit decisions are the same, set to 1 (default )
4. Three trade strategies: Nasdaq, S&P 500, and DOW Jones using the following configuration:
- A Composite SMA Trade Strategy based on all the SMA Configured trade strategies
- The Set Entry cofiguration rules are:
a. Voting Percent
The majority of the signals indicating an investment position (either short or long),
must also meet a minimum percent of 50% across all the strategies in the set.
b. Enter a trade if the last n voting decisions are the same, set to 1 (default )
c. Enter a trade if there is cross-over signaled after applying rules a) and b),
set to False (default)
- The Set Exit configuration rules are:
a. Majority Voting (Default)
- Exit a long trade if the percent of SMA Indicators signaling an exit for a long position
is greater that the percent signaling no-exit
- Exit a short trade if the percent of SMA Indicators signaling an exit for a short position
is greater that the percent signaling no-exit
b. Exit a trade if the last n exit decisions are the same, set to 1 (default )
Backtest:
1. Type: regular
2. Test Period:
1. Begin Date = 2001-01-01
2. End Date = 2001-12-31
portfolio_trade_assets = [ "^DJI", "^IXIC", "^GSPC" ]
dirPathMarketData = '../Data/US_Market_Indixes'
supportedTradeAssets = [ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
beg_date_str = "2000-01-01"
end_date_str = None
ts_marketdat_mng = TradeStrategyMarketDataMng(\
marketDataProviderName = "yahoofinance",
supportedTradeAssets = supportedTradeAssets,
stock_price_col_name = "Adj Close",
fileNameMarketData = "US_Indixes_And_ETFs_MrkData",
dirPathMarketData = dirPathMarketData,
beg_date_str = beg_date_str,
end_date_str = end_date_str,
forceCreateMarketData = False,
interval = "1d" )
brokerTradingObj = SimBrokerTrading()
tsConfDat = TradeStrategyConfigData()
# Set Config
tsConfDat.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "entry" : { 'votingPolicy' : 1, 'incNoInvestInVotingDec' : False,
'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
'lastn_match' : 1, 'cross_over_signal_for_trading' : False },
"exit" : { 'votingPolicy' : 1,
'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
'lastn_match' : 1 }
}
} )
# TS #1
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_1",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 20, 'win_slow' : 100 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #2
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_2",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 10, 'win_slow' : 50 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #3
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_3",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 10, 'win_slow' : 50 } ,
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #4
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_4",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 15, 'win_slow' : 60 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #5
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_5",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 15, 'win_slow' : 75 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #6
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_6",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 7, 'win_slow' : 35 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #7
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_7",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 7, 'win_slow' : 35 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
taRegItemGen = TradeAssetRegisterItemGenerator()
portf_registered_obj = taRegItemGen.createTARegItem(
name_ta_reg_item = "Portfolio C",
# *** Trade Assets & Market Data
portfolio_trade_assets = portfolio_trade_assets,
ts_marketdat_mng = ts_marketdat_mng,
dirPathMarketData = dirPathMarketData,
market_data_period = MarketDataPeriod.Day,
# *** Broker
brokerTradingObj = brokerTradingObj,
# *** T.S. Permutations for each of the following sets of models
enter_exit_config_models = tsConfDat,
# *** Investment Manager Params
minPeriodsBetweenTrades = 1,
initInvestmentPerTradeStrategy = 2000000.0,
capPercentToInvestPerTrade = 100.0,
minInvestPercent = 5.0,
enter_trade_next_open_period = True,
min_account_balance = 1000.0,
portfRebalanceFreq = PortfolioRebalanceFrequency.Never,
portfRebalancePeriods = 1
)
print("Number of configured Trade Strategies: ", len(portf_registered_obj.taRegisterItems) )
tsExecuteEngine = BacktestExecution( \
name = "Backtest for Portfolio C",
timePeriod = DatasetDef(datasetType = DatasetType.Testing,
strBegDate = "2001-01-01",
strEndDate = "2001-12-31" ),
trade_asset_registered_item = portf_registered_obj )
tsExecuteEngine.evaluate()
tsExecuteEngine.getSummaryMetrics().to_excel("Portfolio-C backtest-metrics.xlsx")
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']]
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'trade_asset', 'order_type',
'enter_num_models', 'enter_model', 'enter_model_type',
'exit_num_models', 'exit_model', 'exit_model_type',
'stop_model', 'stop_model_type',
'Start Period', 'End Period',
'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ]
Portfolio D: Long and Multiple Configured LSTM Trade Strategies for US Indixes
Description:
1. Portfolio with 27 trading strategies
2. $2,000,000/strategy
3. No-Rebalance during the backtest
4. 100% capital invested
5. Portfolio investment using equal weights for each trade strategy
Trade Strategies:
1. Three trade strategies: Nasdaq, S&P 500, and DOW Jones with buy-and-hold
2. 21 trade strategies: Nasdaq, S&P 500, and DOW Jones using following LSTM Configurations:
LSTM Models
Parameter #1 #2 #3 #4 #5 #6 #7
epochs 20 20 20 20 20 20 20
no neurons layer 1 20 20 20 20 20 20 20
no neurons layer 2 20 20 20 20 20 20 20
time series length 20 100 50 50 40 30 60
no predictions ahead 3 15 5 5 3 3 5
extend trade dyn Yes Yes Yes Yes Yes Yes Yes
re_evalaute_exit_dyn Yes Yes Yes Yes Yes Yes Yes
enter_if_last_nmatch 1 1 1 1 1 1 1
enter_if_cross_over_sig No No No No No No No
exit_if_last_nmatch 1 1 1 2 1 1 1
3. Three trade strategies: Nasdaq, S&P 500, and DOW Jones using the following Composite
model configuration:
- A Composite LSTM Trade Strategy based on all the LSTM configured trade strategies above
- The Set Entry cofiguration rules are:
a. Majority Voting (default)
b. Enter a trade if the last n voting decisions are the same, set to 1 (default )
c. Enter a trade if there is cross-over signaled after applying rules a) and b),
set to False (default)
- The Set Exit configuration rules are:
a. Majority Voting (Default)
- Exit a long trade if the percent of LSTM Indicators signaling an exit for a long position
is greater that the percent signaling no-exit
- Exit a short trade if the percent of LSTM Indicators signaling an exit for a short position
is greater that the percent signaling no-exit
b. Exit a trade if the last n exit decisions are the same, set to 1 (default )
Backtest:
1. Type: regular
2. AI Models Fit Date Ranges
1. Training Period:
1. Begin Date = 2001-01-01
2. End Date = 2005-12-31
2. Validation Period:
1. Begin Date = 2006-01-01
2. End Date = 2007-12-31
4. Test Period:
1. Begin Date = 2008-01-01
2. End Date = 2008-12-31
portfolio_trade_assets = [ "^DJI", "^IXIC", "^GSPC" ]
dirPathMarketData = '../Data/US_Market_Indixes'
supportedTradeAssets = [ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
beg_date_str = "2000-01-01"
end_date_str = None
ts_marketdat_mng = TradeStrategyMarketDataMng(\
marketDataProviderName = "yahoofinance",
supportedTradeAssets = supportedTradeAssets,
stock_price_col_name = "Adj Close",
fileNameMarketData = "US_Indixes_And_ETFs_MrkData",
dirPathMarketData = dirPathMarketData,
beg_date_str = beg_date_str,
end_date_str = end_date_str,
forceCreateMarketData = False,
interval = "1d" )
brokerTradingObj = SimBrokerTrading()
tsConfDat = TradeStrategyConfigData()
# Set Config
tsConfDat.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "entry" : { 'votingPolicy' : 1, 'incNoInvestInVotingDec' : False,
'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
'lastn_match' : 1, 'cross_over_signal_for_trading' : False },
"exit" : { 'votingPolicy' : 1,
'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
'lastn_match' : 1 }
}
} )
# TS #1
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_lstm_1",
'actions_conf' : { "entry_exit" :
{ 'model' : "lstm",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 3,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #2
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_lstm_2",
'actions_conf' : { "entry_exit" :
{ 'model' : "lstm",
'type' : "ai",
'obj_args' : { 'n_steps' : 100, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 15,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #3
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_lstm_3",
'actions_conf' : { "entry_exit" :
{ 'model' : "lstm",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #4
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_lstm_4",
'actions_conf' : { "entry_exit" :
{ 'model' : "lstm",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 2 } },
},
} )
# TS #5
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_lstm_5",
'actions_conf' : { "entry_exit" :
{ 'model' : "lstm",
'type' : "ai",
'obj_args' : { 'n_steps' : 40, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 3,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #6
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_lstm_6",
'actions_conf' : { "entry_exit" :
{ 'model' : "lstm",
'type' : "ai",
'obj_args' : { 'n_steps' : 30, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 3,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 } ,
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #7
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_lstm_7",
'actions_conf' : { "entry_exit" :
{ 'model' : "lstm",
'type' : "ai",
'obj_args' : { 'n_steps' : 60, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 } ,
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 2 } },
},
} )
taRegItemGen = TradeAssetRegisterItemGenerator()
portf_registered_obj = taRegItemGen.createTARegItem(
name_ta_reg_item = "Portfolio D",
# *** Trade Assets & Market Data
portfolio_trade_assets = portfolio_trade_assets,
ts_marketdat_mng = ts_marketdat_mng,
dirPathMarketData = dirPathMarketData,
market_data_period = MarketDataPeriod.Day,
# *** Broker
brokerTradingObj = brokerTradingObj,
# *** T.S. Permutations for each of the following sets of models
enter_exit_config_models = tsConfDat,
# *** Investment Manager Params
minPeriodsBetweenTrades = 1,
initInvestmentPerTradeStrategy = 2000000.0,
capPercentToInvestPerTrade = 100.0,
minInvestPercent = 5.0,
enter_trade_next_open_period = True,
min_account_balance = 1000.0,
portfRebalanceFreq = PortfolioRebalanceFrequency.Never,
portfRebalancePeriods = 1
)
print("Number of configured Trade Strategies: ", len(portf_registered_obj.taRegisterItems) )
training_period = DatasetDef(datasetType = DatasetType.Training,
strBegDateAIModels = "2000-07-01",
strBegDate = "2001-01-01",
strEndDate = "2005-12-31" )
validation_period = DatasetDef(datasetType = DatasetType.Validation,
strBegDateAIModels = "2005-07-01",
strBegDate = "2006-01-01",
strEndDate = "2007-12-31" )
testing_period = DatasetDef(datasetType = DatasetType.Testing,
strBegDateAIModels = "2007-07-01",
strBegDate = "2008-01-01",
strEndDate = "2008-12-31" )
fit_datasets = FitDatasetsDef( trainingDataset = training_period,
validationDataset = validation_period )
tsExecuteEngine = BacktestExecution( \
name = "Backtest for Portfolio D",
timePeriod = testing_period,
fitDatasets = fit_datasets,
trade_asset_registered_item = portf_registered_obj )
tsExecuteEngine.evaluate()
tsExecuteEngine.getSummaryMetrics().to_excel("Portfolio-D backtest-metrics.xlsx")
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']]
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 'Start Period', 'End Period', 'Time in Market ',
'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ]
Portfolio E: Long and Eleven Distinct Technical Analysis Based Trade Strategies for US Indixes
Description:
1. Portfolio with 39 trading strategies
2. $2,000,000/strategy
3. No-Rebalance during the backtest
4. 100% capital invested
5. Portfolio investment using equal weights for each trade strategy
Trade Strategies:
1. Three trade strategies: Nasdaq, S&P 500, and DOW Jones with buy-and-hold
2. 33 trade strategies: Nasdaq, S&P 500, and DOW Jones using following TA Indicators & Configurations:
See: https://technical-analysis-library-in-python.readthedocs.io/en/latest/index.html for
explanation on the technical indicator specific parameters
TS-No TA-Indicator Parameters
1 sma fast_mav 10
slow_mav 50
enter_if_last_nmatch 2
enter_if_cross_over_sig Yes
exit_if_last_nmatch 1
2 bb window 20
window_dev 1
enter_if_last_nmatch 2
enter_if_cross_over_sig Yes
exit_if_last_nmatch 1
3 macd window_slow 26
window_fast 12
window_sign 9
enter_if_last_nmatch 2
enter_if_cross_over_sig Yes
exit_if_last_nmatch 1
4 rsi enter_long if rsi <= 30
exit_long if rsi > 30
enter_short if rsi >= 70
exit_short if rsi <= 60
enter_if_last_nmatch 2
enter_if_cross_over_sig Yes
exit_if_last_nmatch 1
5 srsi window 14
smooth1 3
smooth2 3
enter_long if stochrsi_d >= 0.5
exit_long if stochrsi_d < 0.5
enter_if_last_nmatch 2
enter_if_cross_over_sig Yes
exit_if_last_nmatch 1
6 adx window 14
enter_if_last_nmatch 2
enter_if_cross_over_sig Yes
exit_if_last_nmatch 1
7 mkama kama_fast_window 10
kama_fast_pow1 2
kama_fast_pow1 30
kama_slow_window 10
kama_slow_pow1 5
kama_slow_pow1 30
enter_if_last_nmatch 2
enter_if_cross_over_sig Yes
exit_if_last_nmatch 1
8 tsi window_slow 25
window_fast 5
enter_if_last_nmatch 2
enter_if_cross_over_sig Yes
exit_if_last_nmatch 1
9 forceidx window 13
enter_if_last_nmatch 2
enter_if_cross_over_sig Yes
exit_if_last_nmatch 1
10 mfi window 14
no mfi points for slope 5
enter_if_last_nmatch 2
enter_if_cross_over_sig Yes
exit_if_last_nmatch 1
11 sma fast_mav 15
slow_mav 60
enter_if_last_nmatch 2
enter_if_cross_over_sig Yes
exit_if_last_nmatch 1
3. Three trade strategies: Nasdaq, S&P 500, and DOW Jones using the following configuration:
- A Composite Trade Strategy based on all the technical-analysis indicators configured
above
- The Set Entry cofiguration rules are:
a. Majority Voting (default)
b. Enter a trade if the last n voting decisions are the same, set to 1 (default )
c. Enter a trade if there is cross-over signaled after applying rules a) and b),
set to False
- The Set Exit configuration rules are:
a. Majority Voting (Default)
b. Exit a trade if the last n exit decisions are the same, set to 1 (default )
Backtest:
1. Type: regular
2. Test Period:
1. Begin Date = 2006-01-01
2. End Date = 2010-12-31
portfolio_trade_assets = [ "^DJI", "^IXIC", "^GSPC" ]
dirPathMarketData = '../Data/US_Market_Indixes'
supportedTradeAssets = [ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
beg_date_str = "2000-01-01"
end_date_str = None
ts_marketdat_mng = TradeStrategyMarketDataMng(\
marketDataProviderName = "yahoofinance",
supportedTradeAssets = supportedTradeAssets,
stock_price_col_name = "Adj Close",
fileNameMarketData = "US_Indixes_And_ETFs_MrkData",
dirPathMarketData = dirPathMarketData,
beg_date_str = beg_date_str,
end_date_str = end_date_str,
forceCreateMarketData = False,
interval = "1d" )
brokerTradingObj = SimBrokerTrading()
tsConfDat = TradeStrategyConfigData()
# Set Config
tsConfDat.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "entry" : { 'votingPolicy' : 1, 'incNoInvestInVotingDec' : False,
'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
'lastn_match' : 1, 'cross_over_signal_for_trading' : False },
"exit" : { 'votingPolicy' : 1,
'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
'lastn_match' : 1 }
}
} )
# TS #1
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_1",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 10, 'win_slow' : 50 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #2
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_2",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 15, 'win_slow' : 60 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #3
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_bb",
'actions_conf' : { "entry_exit" :
{ 'model' : "bb",
'type' : "ta",
'obj_args' : { 'window' : 13, 'window_dev' : 1 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #4
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_macd",
'actions_conf' : { "entry_exit" :
{ 'model' : "macd",
'type' : "ta",
'obj_args' : { 'window_slow' : 26, 'window_fast' : 12, 'window_sign' : 9,
'enter_long_macd_diff' : 0.5 , 'exi_long_macd_diff' : 0.5,
'enter_short_macd_diff' : -0.5, 'exi_short_macd_diff' : -0.5 },
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #5
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_rsi",
'actions_conf' : { "entry_exit" :
{ 'model' : "rsi",
'type' : "ta",
'obj_args' : { 'rsi_enter_long' : 30.0, 'rsi_exit_long' : 30.0,
'rsi_enter_short' : 70.0, 'rsi_exit_short' : 70.0 },
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #6
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_srsi",
'actions_conf' : { "entry_exit" :
{ 'model' : "srsi",
'type' : "ta",
'obj_args' : { 'window' : 14, 'smooth1' : 3, 'smooth2' : 3,
'srsi_enter_long' : 0.8, 'srsi_exit_long' : 0.8,
'srsi_enter_short' : 0.2, 'srsi_exit_short' : 0.2 },
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #7
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_adx",
'actions_conf' : { "entry_exit" :
{ 'model' : "adx",
'type' : "ta",
'obj_args' : { 'window' : 14, 'adx_enter_long_ge' : 14, 'adx_exit_long_lt' : 14,
'adx_enter_short_ge' : 14, 'adx_exit_short_lt' : 14 },
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #8
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_kama",
'actions_conf' : { "entry_exit" :
{ 'model' : "kama",
'type' : "ta",
'obj_args' : { 'window_fast' : 10, 'pow1_fast' : 2, 'pow2_fast' : 30,
'window_slow' : 10, 'pow1_slow' : 5, 'pow2_slow' : 30 },
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #9
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_tsi",
'actions_conf' : { "entry_exit" :
{ 'model' : "tsi",
'type' : "ta",
'obj_args' : { 'window_slow' : 25, 'window_fast' : 5 },
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #10
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_forceindex",
'actions_conf' : { "entry_exit" :
{ 'model' : "forceindex",
'type' : "ta",
'obj_args' : { 'window' : 39 },
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #11
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_mfi",
'actions_conf' : { "entry_exit" :
{ 'model' : "mfi",
'type' : "ta",
'obj_args' : { 'window' : 14, 'long_slope_win' : 15, 'short_slope_win' : 15 },
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
taRegItemGen = TradeAssetRegisterItemGenerator()
portf_registered_obj = taRegItemGen.createTARegItem(
name_ta_reg_item = "Portfolio E",
# *** Trade Assets & Market Data
portfolio_trade_assets = portfolio_trade_assets,
ts_marketdat_mng = ts_marketdat_mng,
dirPathMarketData = dirPathMarketData,
market_data_period = MarketDataPeriod.Day,
# *** Broker
brokerTradingObj = brokerTradingObj,
# *** T.S. Permutations for each of the following sets of models
enter_exit_config_models = tsConfDat,
# *** Investment Manager Params
minPeriodsBetweenTrades = 1,
initInvestmentPerTradeStrategy = 2000000.0,
capPercentToInvestPerTrade = 100.0,
minInvestPercent = 5.0,
enter_trade_next_open_period = True,
min_account_balance = 1000.0,
portfRebalanceFreq = PortfolioRebalanceFrequency.Never,
portfRebalancePeriods = 1
)
print("Number of configured Trade Strategies: ", len(portf_registered_obj.taRegisterItems) )
tsExecuteEngine = BacktestExecution( \
name = "Backtest for Portfolio E",
timePeriod = DatasetDef(datasetType = DatasetType.Testing,
strBegDate = "2006-01-01",
strEndDate = "2010-12-31" ),
trade_asset_registered_item = portf_registered_obj )
tsExecuteEngine.evaluate()
tsExecuteEngine.getSummaryMetrics().to_excel("Portfolio-E backtest-metrics.xlsx")
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']]
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 'Start Period', 'End Period', 'Time in Market ',
'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ]
Portfolio F: Long and Multiple Configured AI-Modeled Trade Strategies for US Indixes
Description:
1. Portfolio with 30 trading strategies
2. $2,000,000/strategy
3. No-Rebalance during the backtest
4. 100% capital invested
5. Portfolio investment using equal weights for each trade strategy
Trade Strategies:
1. Three trade strategies: Nasdaq, S&P 500, and DOW Jones with buy-and-hold
2. 24 trade strategies: Nasdaq, S&P 500, and DOW Jones using the following AI-Models
and corresponding configurations:
Trading AI-Models
Parameter #1 #2 #3 #4 #5 #6 #7
ai-model GRU LSTM Conv1d-GRU Conv1d-LSTM Wavenet Wavenet-GRU GRU
epochs 20 20 20 20 20 20 20
no neurons layer 1 20 20 20 20 - 20 20
no neurons layer 2 20 20 20 20 - 20 20
time series length 50 50 50 50 50 50 40
no predictions ahead 5 5 5 5 5 5 3
extend trade dyn Yes Yes Yes Yes Yes Yes Yes
re_evalaute_exit_dyn Yes Yes Yes Yes Yes Yes Yes
enter_if_last_nmatch 1 1 1 1 1 1 1
enter_if_cross_over_sig No No No No No No No
exit_if_last_nmatch 1 1 1 1 1 1 1
Parameter #8
ai-model Wavenet-LSTM
epochs 20
no neurons layer 1 20
no neurons layer 2 20
time series length 50
no predictions ahead 5
extend trade dyn Yes
re_evalaute_exit_dyn Yes
enter_if_last_nmatch 1
enter_if_cross_over_sig No
exit_if_last_nmatch 1
Note:
- the parameters "no neurons layer 1" and "no neurons layer 2" are only applicable to
AI Models that have GRU or LSTM layers.
- Conv1d is a convulation layer in one dimension (configured with 40 filters )
- Wavenet is an AI Architectured based on a set of Convolutional Layers
3. Three trade strategies: Nasdaq, S&P 500, and DOW Jones using the following Composite
model configuration:
- A Composite Trade Strategy based on all the AI Trading Models configured above
- The Set Entry cofiguration rules are:
a. Majority Voting (default)
b. Enter a trade if the last n voting decisions are the same, set to 1 (default )
c. Enter a trade if there is cross-over signaled after applying rules a) and b),
set to False (default)
- The Set Exit configuration rules are:
a. Majority Voting (Default)
- Exit a long trade if the percent of Trading AI Models signaled an exit for a long position
is greater that the percent signaling no-exit
- Exit a short trade if the percent of Trading AI Models signaled an exit for a short position
is greater that the percent signaling no-exit
b. Exit a trade if the last n exit decisions are the same, set to 1 (default )
Backtest:
1. Type: regular
2. AI Models Fit Date Ranges
1. Training Period:
1. Begin Date = 2002-01-01
2. End Date = 2006-12-31
2. Validation Period:
1. Begin Date = 2007-01-01
2. End Date = 2008-12-31
3. Test Period:
1. Begin Date = 2009-01-01
2. End Date = 2009-12-31
portfolio_trade_assets = [ "^DJI", "^IXIC", "^GSPC" ]
dirPathMarketData = '../Data/US_Market_Indixes'
supportedTradeAssets = [ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
beg_date_str = "2000-01-01"
end_date_str = None
ts_marketdat_mng = TradeStrategyMarketDataMng(\
marketDataProviderName = "yahoofinance",
supportedTradeAssets = supportedTradeAssets,
stock_price_col_name = "Adj Close",
fileNameMarketData = "US_Indixes_And_ETFs_MrkData",
dirPathMarketData = dirPathMarketData,
beg_date_str = beg_date_str,
end_date_str = end_date_str,
forceCreateMarketData = False,
interval = "1d" )
brokerTradingObj = SimBrokerTrading()
# Define Metadata for several Trading AI-Models for several Trade Strategies in the portfolio and one
# Trade Strategy based on a composite set of all Trading AI-Models. The composite trade strategy
# uses Majority Voting for entering and exiting a trade (default setting)
# The configuraiton data for each Trade Strategy is defined via a JSON/dict, and
# they are added to the TradeStrategyConfigData() object
#
# This configuration method is a short-cut when creating many trade strategies in a portfolio, or
# a composite of many trade strategies. The JSON format follows the general format:
#
# *** Trade Strategy Config:
#
# 1. ts_unique_tag : unique tag to identify a trade strategy in a set
# 2. actions_conf : dict,
# Description: contains the configuration data for each action in a trade strategy, only
# the "entry_exit", sub-tag is required
# Child tags:
# "entry_exit" : required
# "stop_lost" : optional
# "pos_sizing" : optional
# "pyramiding" : optional
# 3. The format of each child-tag/action follows the same parameters as when defined via the class,
# 4. obj_args : custom set of parameters passed to the defined model defined via the model tag, this
# is a dynamic set of parameters and specific to each model, some share common inputs.
#
# Supported built-in models, for the entry_exit action:
# [ "sma", "bb", "macd", "rsi", "srsi", "adx", "kama", "tsi",
# "forceindex", "mfi", 'conv1d_gru', 'conv1d_lstm', 'wavenet',
# 'wavenet_gru', 'wavenet_lstm', 'lstm', 'gru' ]
#
# Custom models can be added via a custom function. The second strategy in the configuration
# below ('ts_unique_tag' : "ts_gru_1") , defines the "custom_create_func" tag and sets equal to
# "create_actions_ai_ts_model", this function should be already defined or imported. Thus for
# trade strategy #2, the user custom function is used. Note, that for trade strategy: ts_gru_2
# the model is also set to "gru", but in this case it is using the built-in gru model.
# The actual implementantions for all supported models are included in this Jupyter Notebook, at
# the beg. of this portfolio example, and a user can copy and altered as they see fit, it would
# affect the built-in functions, which are scope in a pythong package.
#
#
# *** Trade Strategy Set Config:
#
# There is only one set configuration, and it is defined to apply policies on how to treat the
# set actions, this configuration is optional, and defaults for each action are defined below
#
# "entry" : optional
# Defines the policy to drive the trade decision to follow from the set. As explained in earlier
# examples.
# Default policy parameters are:
# Majority Voting,
# incNoInvestInVotingDec = False,
# lastn_match = 1
# cross_over_signal_for_trading
#
# "exit" : optional
# Defines the policy to drive the exit decision to follow from the set. As explained in earlier
# examples.
# Default policy parameters are:
# Majority Voting,
# lastn_match = 1
#
tsConfDat = TradeStrategyConfigData()
# Set Config
tsConfDat.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "entry" : { 'votingPolicy' : 1, 'incNoInvestInVotingDec' : False,
'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
'lastn_match' : 1, 'cross_over_signal_for_trading' : False },
"exit" : { 'votingPolicy' : 1,
'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
'lastn_match' : 1 }
}
} )
# TS #1
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_gru_1",
'actions_conf' : { "entry_exit" :
{ 'model' : "gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #2
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_lstm",
'actions_conf' : { "entry_exit" :
{ 'model' : "lstm",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #3
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_conv1d_gru",
'actions_conf' : { "entry_exit" :
{ 'model' : "conv1d_gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #4
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_conv1d_lstm",
'actions_conf' : { "entry_exit" :
{ 'model' : "conv1d_lstm",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #5
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_wavenet",
'actions_conf' : { "entry_exit" :
{ 'model' : "wavenet",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #6
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_wavenet_gru",
'actions_conf' : { "entry_exit" :
{ 'model' : "wavenet_gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #7
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_wavenet_lstm",
'actions_conf' : { "entry_exit" :
{ 'model' : "wavenet_lstm",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #8
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_gru_2",
'actions_conf' : { "entry_exit" :
{ 'model' : "gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 40, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 3,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
taRegItemGen = TradeAssetRegisterItemGenerator()
portf_registered_obj = taRegItemGen.createTARegItem(
name_ta_reg_item = "Portfolio F",
# *** Trade Assets & Market Data
portfolio_trade_assets = portfolio_trade_assets,
ts_marketdat_mng = ts_marketdat_mng,
dirPathMarketData = dirPathMarketData,
market_data_period = MarketDataPeriod.Day,
# *** Broker
brokerTradingObj = brokerTradingObj,
# *** T.S. Permutations for each of the following sets of models
enter_exit_config_models = tsConfDat,
# *** Investment Manager Params
minPeriodsBetweenTrades = 1,
initInvestmentPerTradeStrategy = 2000000.0,
capPercentToInvestPerTrade = 100.0,
minInvestPercent = 5.0,
enter_trade_next_open_period = True,
min_account_balance = 1000.0,
portfRebalanceFreq = PortfolioRebalanceFrequency.Never,
portfRebalancePeriods = 1
)
print("Number of configured Trade Strategies: ", len(portf_registered_obj.taRegisterItems) )
training_period = DatasetDef(datasetType = DatasetType.Training,
strBegDateAIModels = "2001-07-01",
strBegDate = "2002-01-01",
strEndDate = "2006-12-31" )
validation_period = DatasetDef(datasetType = DatasetType.Validation,
strBegDateAIModels = "2006-07-01",
strBegDate = "2007-01-01",
strEndDate = "2008-12-31" )
testing_period = DatasetDef(datasetType = DatasetType.Testing,
strBegDateAIModels = "2008-07-01",
strBegDate = "2009-01-01",
strEndDate = "2009-12-31" )
fit_datasets = FitDatasetsDef( trainingDataset = training_period,
validationDataset = validation_period )
tsExecuteEngine = BacktestExecution( \
name = "Backtest for Portfolio F",
timePeriod = testing_period,
fitDatasets = fit_datasets,
trade_asset_registered_item = portf_registered_obj )
tsExecuteEngine.evaluate()
tsExecuteEngine.getSummaryMetrics().to_excel("Portfolio-F backtest-metrics.xlsx")
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']]
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 'Start Period', 'End Period', 'Time in Market ',
'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ]
Portfolio G: Combines all Trade Strategies in Portfolio E and F
Description:
1. Portfolio with 63 trading strategies
2. $2,000,000/strategy
3. No-Rebalance during the backtest
4. 100% capital invested
5. Portfolio investment using equal weights for each trade strategy
Trade Strategies:
1. Three trade strategies: Nasdaq, S&P 500, and DOW Jones with buy-and-hold
2. Fifty-Seven trade strategies, 19 trade strategies per US Index, as defined in
Portfolio E and F
3. Three trade strategies: Nasdaq, S&P 500, and DOW Jones using the following Composite
model configuration:
- A Composite Trade Strategy based on all the Trading Models configured above per US Index
- The Set Entry cofiguration rules are:
a. Majority Voting (default)
b. Enter a trade if the last n voting decisions are the same, set to 1 (default )
c. Enter a trade if there is cross-over signaled after applying rules a) and b),
set to False (default)
- The Set Exit configuration rules are:
a. Majority Voting (Default)
- Exit a long trade if the percent of Trading Models signaled an exit for a long position
is greater that the percent signaling no-exit
- Exit a short trade if the percent of Trading Models signaled an exit for a short position
is greater that the percent signaling no-exit
b. Exit a trade if the last n exit decisions are the same, set to 1 (default )
Backtest:
1. Type: regular
2. AI Models Fit Date Ranges
1. Training Period:
1. Begin Date = 2001-01-01
2. End Date = 2006-12-31
2. Validation Period:
1. Begin Date = 2007-01-01
2. End Date = 2008-12-31
3. Test Period:
1. Begin Date = 2009-01-01
2. End Date = 2009-12-31
portfolio_trade_assets = [ "^DJI", "^IXIC", "^GSPC" ]
dirPathMarketData = '../Data/US_Market_Indixes'
supportedTradeAssets = [ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
beg_date_str = "2000-01-01"
end_date_str = None
ts_marketdat_mng = TradeStrategyMarketDataMng(\
marketDataProviderName = "yahoofinance",
supportedTradeAssets = supportedTradeAssets,
stock_price_col_name = "Adj Close",
fileNameMarketData = "US_Indixes_And_ETFs_MrkData",
dirPathMarketData = dirPathMarketData,
beg_date_str = beg_date_str,
end_date_str = end_date_str,
forceCreateMarketData = False,
interval = "1d" )
brokerTradingObj = SimBrokerTrading()
tsConfDat = TradeStrategyConfigData()
# Set Config
tsConfDat.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "entry" : { 'votingPolicy' : 1, 'incNoInvestInVotingDec' : False,
'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
'lastn_match' : 1, 'cross_over_signal_for_trading' : False },
"exit" : { 'votingPolicy' : 1,
'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
'lastn_match' : 1 }
}
} )
# TS #1
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_gru_1",
'actions_conf' : { "entry_exit" :
{ 'model' : "gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #2
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_lstm",
'actions_conf' : { "entry_exit" :
{ 'model' : "lstm",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #3
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_conv1d_gru",
'actions_conf' : { "entry_exit" :
{ 'model' : "conv1d_gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #4
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_conv1d_lstm",
'actions_conf' : { "entry_exit" :
{ 'model' : "conv1d_lstm",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #5
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_wavenet",
'actions_conf' : { "entry_exit" :
{ 'model' : "wavenet",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #6
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_wavenet_gru",
'actions_conf' : { "entry_exit" :
{ 'model' : "wavenet_gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #7
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_wavenet_lstm",
'actions_conf' : { "entry_exit" :
{ 'model' : "wavenet_lstm",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #8
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_gru_2",
'actions_conf' : { "entry_exit" :
{ 'model' : "gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 40, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 3,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #9
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_1",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 10, 'win_slow' : 50 } ,
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #10
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_2",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 15, 'win_slow' : 60 } ,
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #11
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_bb",
'actions_conf' : { "entry_exit" :
{ 'model' : "bb",
'type' : "ta",
'obj_args' : { 'window' : 13, 'window_dev' : 1 } ,
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #12
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_macd",
'actions_conf' : { "entry_exit" :
{ 'model' : "macd",
'type' : "ta",
'obj_args' : { 'window_slow' : 26, 'window_fast' : 12, 'window_sign' : 9,
'enter_long_macd_diff' : 0.5 , 'exi_long_macd_diff' : 0.5,
'enter_short_macd_diff' : -0.5, 'exi_short_macd_diff' : -0.5 },
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #13
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_rsi",
'actions_conf' : { "entry_exit" :
{ 'model' : "rsi",
'type' : "ta",
'obj_args' : { 'rsi_enter_long' : 30.0, 'rsi_exit_long' : 30.0,
'rsi_enter_short' : 70.0, 'rsi_exit_short' : 70.0 },
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #14
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_srsi",
'actions_conf' : { "entry_exit" :
{ 'model' : "srsi",
'type' : "ta",
'obj_args' : { 'window' : 14, 'smooth1' : 3, 'smooth2' : 3,
'srsi_enter_long' : 0.8, 'srsi_exit_long' : 0.8,
'srsi_enter_short' : 0.2, 'srsi_exit_short' : 0.2 },
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #15
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_adx",
'actions_conf' : { "entry_exit" :
{ 'model' : "adx",
'type' : "ta",
'obj_args' : { 'window' : 14, 'adx_enter_long_ge' : 14, 'adx_exit_long_lt' : 14,
'adx_enter_short_ge' : 14, 'adx_exit_short_lt' : 14 },
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #16
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_kama",
'actions_conf' : { "entry_exit" :
{ 'model' : "kama",
'type' : "ta",
'obj_args' : { 'window_fast' : 10, 'pow1_fast' : 2, 'pow2_fast' : 30,
'window_slow' : 10, 'pow1_slow' : 5, 'pow2_slow' : 30 },
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #17
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_tsi",
'actions_conf' : { "entry_exit" :
{ 'model' : "tsi",
'type' : "ta",
'obj_args' : { 'window_slow' : 25, 'window_fast' : 5 },
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #118
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_forceindex",
'actions_conf' : { "entry_exit" :
{ 'model' : "forceindex",
'type' : "ta",
'obj_args' : { 'window' : 39 },
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #19
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_mfi",
'actions_conf' : { "entry_exit" :
{ 'model' : "mfi",
'type' : "ta",
'obj_args' : { 'window' : 14, 'long_slope_win' : 15, 'short_slope_win' : 15 },
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
taRegItemGen = TradeAssetRegisterItemGenerator()
portf_registered_obj = taRegItemGen.createTARegItem(
name_ta_reg_item = "Portfolio G",
# *** Trade Assets & Market Data
portfolio_trade_assets = portfolio_trade_assets,
ts_marketdat_mng = ts_marketdat_mng,
dirPathMarketData = dirPathMarketData,
market_data_period = MarketDataPeriod.Day,
# *** Broker
brokerTradingObj = brokerTradingObj,
# *** T.S. Permutations for each of the following sets of models
enter_exit_config_models = tsConfDat,
# *** Investment Manager Params
minPeriodsBetweenTrades = 1,
initInvestmentPerTradeStrategy = 2000000.0,
capPercentToInvestPerTrade = 100.0,
minInvestPercent = 5.0,
enter_trade_next_open_period = True,
min_account_balance = 1000.0,
portfRebalanceFreq = PortfolioRebalanceFrequency.Never,
portfRebalancePeriods = 1
)
print("Number of configured Trade Strategies: ", len(portf_registered_obj.taRegisterItems) )
training_period = DatasetDef(datasetType = DatasetType.Training,
strBegDateAIModels = "2000-07-01",
strBegDate = "2001-01-01",
strEndDate = "2006-12-31" )
validation_period = DatasetDef(datasetType = DatasetType.Validation,
strBegDateAIModels = "2006-07-01",
strBegDate = "2007-01-01",
strEndDate = "2008-12-31" )
testing_period = DatasetDef(datasetType = DatasetType.Testing,
strBegDateAIModels = "2008-07-01",
strBegDate = "2009-01-01",
strEndDate = "2009-12-31" )
fit_datasets = FitDatasetsDef( trainingDataset = training_period,
validationDataset = validation_period )
tsExecuteEngine = BacktestExecution( \
name = "Backtest for Portfolio G",
timePeriod = testing_period,
fitDatasets = fit_datasets,
trade_asset_registered_item = portf_registered_obj )
tsExecuteEngine.evaluate()
tsExecuteEngine.getSummaryMetrics().to_excel("Portfolio-G backtest-metrics.xlsx")
DOW Jones
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']].\
query('TA_Reg_Name.str.contains("DJI")', engine='python')
Nasdaq
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']].\
query('TA_Reg_Name.str.contains("IXIC")', engine='python')
S&P 500
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']].\
query('TA_Reg_Name.str.contains("GSPC")', engine='python')
Dow Jones
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 'Start Period', 'End Period', 'Time in Market ',
'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ].\
query('trade_asset == "^DJI" ')
Nasdaq
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 'Start Period', 'End Period', 'Time in Market ',
'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ].\
query('trade_asset == "^IXIC" ')
S&P 500
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 'Start Period', 'End Period', 'Time in Market ',
'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ].\
query('trade_asset == "^GSPC" ')
Portfolio H: Utilized Leveraged ETFs for Trading on The Model Security
- All models are trained on their corresponding US Index/model, but the trade enter via a broker is with
the underlying leveraged ETF.
- $2,000,000/strategy
- ETF data for US Indixes not available until 2011 in yahoo finance
- Seven Trade Strategies are executed with ETF trading enable
- Additionally, there is a composite trade strategy for all ETF strategies a
Backtest:
1. Type: regular
2. AI Models Fit Date Ranges
1. Training Period:
1. Begin Date = 2007-01-01
2. End Date = 2012-12-31
2. Validation Period:
1. Begin Date = 2013-01-01
2. End Date = 2014-12-31
3. Test Period:
1. Begin Date = 2015-01-01
2. End Date = 2015-12-31
portfolio_trade_assets = [ "^DJI", "^IXIC", "^GSPC" ]
dirPathMarketData = '../Data/US_Market_Indixes'
supportedTradeAssets = [ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
beg_date_str = "2000-01-01"
end_date_str = None
ts_marketdat_mng = TradeStrategyMarketDataMng(\
marketDataProviderName = "yahoofinance",
supportedTradeAssets = supportedTradeAssets,
stock_price_col_name = "Adj Close",
fileNameMarketData = "US_Indixes_And_ETFs_MrkData",
dirPathMarketData = dirPathMarketData,
beg_date_str = beg_date_str,
end_date_str = end_date_str,
forceCreateMarketData = False,
interval = "1d" )
MarketData.getDateRangesForStocks( ts_marketdat_mng.marketDataObj.getDataFrame() )
brokerTradingObj = SimBrokerTrading()
tsConfDat = TradeStrategyConfigData()
# Set Config
tsConfDat.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "entry" : { 'votingPolicy' : 1, 'incNoInvestInVotingDec' : False,
'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
'lastn_match' : 1, 'cross_over_signal_for_trading' : False },
"exit" : { 'votingPolicy' : 1,
'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
'lastn_match' : 1 }
}
} )
# TS #1
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_gru_1",
'actions_conf' : { "entry_exit" :
{ 'model' : "gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #2
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_lstm",
'actions_conf' : { "entry_exit" :
{ 'model' : "lstm",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #3
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_conv1d_gru",
'actions_conf' : { "entry_exit" :
{ 'model' : "conv1d_gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #4
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_conv1d_lstm",
'actions_conf' : { "entry_exit" :
{ 'model' : "conv1d_lstm",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #5
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_wavenet",
'actions_conf' : { "entry_exit" :
{ 'model' : "wavenet",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #6
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_wavenet_gru",
'actions_conf' : { "entry_exit" :
{ 'model' : "wavenet_gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #7
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_wavenet_lstm",
'actions_conf' : { "entry_exit" :
{ 'model' : "wavenet_lstm",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
taRegItemGen = TradeAssetRegisterItemGenerator()
portf_registered_obj = taRegItemGen.createTARegItem(
name_ta_reg_item = "Portfolio H",
# *** Trade Assets & Market Data
portfolio_trade_assets = portfolio_trade_assets,
ts_marketdat_mng = ts_marketdat_mng,
dirPathMarketData = dirPathMarketData,
market_data_period = MarketDataPeriod.Day,
# *** Broker
brokerTradingObj = brokerTradingObj,
# *** T.S. Permutations for each of the following sets of models
enter_exit_config_models = tsConfDat,
# *** Investment Manager Params
minPeriodsBetweenTrades = 1,
initInvestmentPerTradeStrategy = 2000000.0,
capPercentToInvestPerTrade = 100.0,
minInvestPercent = 5.0,
enter_trade_next_open_period = True,
min_account_balance = 1000.0,
portfRebalanceFreq = PortfolioRebalanceFrequency.Never,
portfRebalancePeriods = 1,
# Trade On ETF Params
trade_on_ETFs = True,
trade_assets_etf_map = { "^DJI" : [ "UDOW", "SDOW"],
"^IXIC" : [ "TQQQ", "SQQQ"],
"^GSPC" : [ "SPXL", "SPXS"] },
)
print("Number of configured Trade Strategies: ", len(portf_registered_obj.taRegisterItems) )
training_period = DatasetDef(datasetType = DatasetType.Training,
strBegDateAIModels = "2006-07-01",
strBegDate = "2007-01-01",
strEndDate = "2012-12-31" )
validation_period = DatasetDef(datasetType = DatasetType.Validation,
strBegDateAIModels = "2012-07-01",
strBegDate = "2013-01-01",
strEndDate = "2014-12-31" )
testing_period = DatasetDef(datasetType = DatasetType.Testing,
strBegDateAIModels = "2014-07-01",
strBegDate = "2015-01-01",
strEndDate = "2015-12-31" )
fit_datasets = FitDatasetsDef( trainingDataset = training_period,
validationDataset = validation_period )
tsExecuteEngine = BacktestExecution( \
name = "Backtest for Portfolio H",
timePeriod = testing_period,
fitDatasets = fit_datasets,
trade_asset_registered_item = portf_registered_obj )
tsExecuteEngine.evaluate()
tsExecuteEngine.getSummaryMetrics().to_excel("Portfolio-H backtest-metrics.xlsx")
DOW Jones
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']].\
query('TA_Reg_Name.str.contains("DJI")', engine='python')
Nasdaq
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']].\
query('TA_Reg_Name.str.contains("IXIC")', engine='python')
S&P 500
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']].\
query('TA_Reg_Name.str.contains("GSPC")', engine='python')
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 'Start Period', 'End Period', 'Time in Market ',
'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ].\
query('trade_asset == "^DJI"' )
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 'Start Period', 'End Period', 'Time in Market ',
'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ].\
query('trade_asset == "^IXIC"' )
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 'Start Period', 'End Period', 'Time in Market ',
'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ].\
query('trade_asset == "^GSPC"' )
Portfolio I: Monthly Rebalance of Funds in the Portfolio
- Same strategies as defined and explained in Portfolio C.
- Only difference is the Portfolio Investment Manager is configured to balance funds monthly,
using an equal weights policy.
Backtest:
1. Type: regular
2. Test Period:
1. Begin Date = 2012-01-01
2. End Date = 2015-12-31
portfolio_trade_assets = [ "^DJI", "^IXIC", "^GSPC" ]
dirPathMarketData = '../Data/US_Market_Indixes'
supportedTradeAssets = [ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
beg_date_str = "2000-01-01"
end_date_str = None
ts_marketdat_mng = TradeStrategyMarketDataMng(\
marketDataProviderName = "yahoofinance",
supportedTradeAssets = supportedTradeAssets,
stock_price_col_name = "Adj Close",
fileNameMarketData = "US_Indixes_And_ETFs_MrkData",
dirPathMarketData = dirPathMarketData,
beg_date_str = beg_date_str,
end_date_str = end_date_str,
forceCreateMarketData = False,
interval = "1d" )
brokerTradingObj = SimBrokerTrading()
tsConfDat = TradeStrategyConfigData()
# Set Config
tsConfDat.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "entry" : { 'votingPolicy' : 1, 'incNoInvestInVotingDec' : False,
'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
'lastn_match' : 1, 'cross_over_signal_for_trading' : False },
"exit" : { 'votingPolicy' : 1,
'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
'lastn_match' : 1 }
}
} )
# TS #1
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_1",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 20, 'win_slow' : 100 } ,
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : True },
'exit_policy_args' : { 'lastn_match' : 2 } },
},
} )
# TS #2
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_2",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 10, 'win_slow' : 50 } ,
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : True },
'exit_policy_args' : { 'lastn_match' : 2 } },
},
} )
# TS #3
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_3",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 10, 'win_slow' : 50 } ,
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : True },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #4
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_4",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 15, 'win_slow' : 60 } ,
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : True },
'exit_policy_args' : { 'lastn_match' : 2 } },
},
} )
# TS #5
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_5",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 15, 'win_slow' : 75 } ,
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : True },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #6
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_6",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 7, 'win_slow' : 35 } ,
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : True },
'exit_policy_args' : { 'lastn_match' : 2 } },
},
} )
# TS #7
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_7",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 7, 'win_slow' : 35 } ,
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : True },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
taRegItemGen = TradeAssetRegisterItemGenerator()
portf_registered_obj = taRegItemGen.createTARegItem(
name_ta_reg_item = "Portfolio I",
# *** Trade Assets & Market Data
portfolio_trade_assets = portfolio_trade_assets,
ts_marketdat_mng = ts_marketdat_mng,
dirPathMarketData = dirPathMarketData,
market_data_period = MarketDataPeriod.Day,
# *** Broker
brokerTradingObj = brokerTradingObj,
# *** T.S. Permutations for each of the following sets of models
enter_exit_config_models = tsConfDat,
# *** Investment Manager Params
minPeriodsBetweenTrades = 1,
initInvestmentPerTradeStrategy = 2000000.0,
capPercentToInvestPerTrade = 100.0,
minInvestPercent = 5.0,
enter_trade_next_open_period = True,
min_account_balance = 1000.0,
portfRebalanceFreq = PortfolioRebalanceFrequency.Monthly,
portfRebalancePeriods = 1
)
print("Number of configured Trade Strategies: ", len(portf_registered_obj.taRegisterItems) )
tsExecuteEngine = BacktestExecution( \
name = "Backtest for Portfolio I",
timePeriod = DatasetDef(datasetType = DatasetType.Testing,
strBegDate = "2012-01-01",
strEndDate = "2015-12-31" ),
trade_asset_registered_item = portf_registered_obj )
tsExecuteEngine.evaluate()
tsExecuteEngine.getSummaryMetrics().to_excel("Portfolio-I backtest-metrics.xlsx")
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']]
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 'Start Period', 'End Period', 'Time in Market ',
'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ]
Portfolio J: Trade Strategies with different Market Data Sources (Quandal, YahooFinance, User-Defined DataFrame)
- Futures data is sourced from Quandal (Cotton, Soy Beans, and S&P 500 futures)
- US Equity indexes from Yahoo-Finance
- Leverage ETFs TQQQ and SQQQ from the user-defined DataFrame
- Multiple SMA Models, and LSTM, GRU, MACD, and RSI Models defined to use with each trading asset
- Additionally, there is a composite trade strategy for all Futures, and one composite trade
strategy for the US Index equities
- Buy-and-Hold strategies for each trade asset for comparison
- $2,000,000/strategy
Backtest:
1. Type: regular
2. AI Models Fit Date Ranges
1. Training Period:
1. Begin Date = 2002-01-01
2. End Date = 2006-12-31
2. Validation Period:
1. Begin Date = 2007-01-01
2. End Date = 2008-12-31
3. Test Period:
1. Begin Date = 2009-01-01
2. End Date = 2009-12-31
portfolio_trade_assets_yf = [ "^DJI", "^IXIC", "^GSPC" ]
dirPathMarketData = '../Data/US_Market_Indixes'
supportedTradeAssets = [ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
beg_date_str = "2000-01-01"
end_date_str = None
ts_marketdat_mng_yf = TradeStrategyMarketDataMng(\
marketDataProviderName = "yahoofinance",
supportedTradeAssets = supportedTradeAssets,
stock_price_col_name = "Adj Close",
fileNameMarketData = "US_Indixes_And_ETFs_MrkData",
dirPathMarketData = dirPathMarketData,
beg_date_str = beg_date_str,
end_date_str = end_date_str,
forceCreateMarketData = False,
interval = "1d" )
User can provide their own market data via a Pandas DataFrame
Requirements:
1. DataFrame Index : must be called "Date", and be of datetime format
2. Index column : All data associated with a given trade asset. Same exact format as the
yahoofinance above
3. The rest of the columns in the dataframe can be named anything. However, it is recommended
they used standard names as the ones in YahooFinance above; this will make all built-in
AI and Technical Analysis Models available.
4. Note, interval, supportedTradeAssets are constraint and not enforced; the data that is passed
in the dataframe is what is supported.
ts_marketdat_mng_df = TradeStrategyMarketDataMng(\
marketDataProviderName = "dataframe",
marketDataDF = ts_marketdat_mng_yf.marketDataObj.getDataFrame(),
supportedTradeAssets = supportedTradeAssets,
stock_price_col_name = "Adj Close",
fileNameMarketData = "US_Indixes_And_ETFs_MrkData_DF",
dirPathMarketData = dirPathMarketData,
beg_date_str = beg_date_str,
end_date_str = end_date_str,
forceCreateMarketData = False,
interval = "1d" )
ts_marketdat_mng_df.marketDataObj.getDataFrame()
Download the following data from Quandal:
CHRIS/CME_SP1
Where CHRIS is the Quandal Data Provider, and the name after the / is the Futures symbol.
The format of the JSON to download from Quandal is:
{ quandal-path :
[ description of data,
[ columns to extract from the returned Quandal DataFrame ],
{ "Quandal_Column" : "Rename Quandal Column" }
]
}
Note:
1. The nested dictionary to rename the original downloaded Quandal data, it is provided since Quandal does
not have standard output column names.
- Futures data from different data sources might have different returned column names for the same
state, that is "Close" vs. "close", etc.
- For sharing the same market data manager object it is recommended to rename the columns to have
standard names, and match the ones provided by Yahoo Finance
2. Yahoo Finance returns standard equity column names
3. All implemented AI and Technical Models used standard column names (same as Yahoo Finance)
Columns: Adj Close, Close, Open, High, Low, Volume
Index: Datetime
4. In order to use the implemented models the Quandal Market Data or any Custom Market Data must have
similar named columns, or the user can implement his own models and use whatever column names he/she
prefers.
5. In this example, the Quandal data source does not provide all standard column names, only open,
which is re-named to 'Adj Close'. Therefore only some of the built models will be available,
as they required High, Low, such as Bollinger Bands
indexQuantCodeMap = {
"CHRIS/CME_S2" : ["SoyBeans", ["Open", "Volume"], { "Open" : "Adj Close" } ],
"CHRIS/ICE_CT1" : ["Cotton", ["Open", "Volume"], { "Open" : "Adj Close" } ],
"CHRIS/CME_SP1" : ["S&P_500", ["Open", "Volume"], { "Open" : "Adj Close" } ] }
portfolio_trade_assets_quandal = list ( indexQuantCodeMap.keys() )
dirPathMarketDataQuandl = '../Data/TSMarketDat'
beg_date_for_feature_creation = "2000-10-01"
beg_date_str = "2001-01-01"
end_date_str = "2010-12-31"
ts_marketdat_mng_quandal = TradeStrategyMarketDataMng(\
marketDataProviderName = "quandl",
supportedTradeAssets = portfolio_trade_assets_quandal,
stock_price_col_name = "Adj Close",
fileNameMarketData = "Quandl_Test_1_PorfolioRegisterItem_Portf_J",
dirPathMarketData = dirPathMarketDataQuandl,
beg_date_str = beg_date_for_feature_creation,
end_date_str = end_date_str,
interval = "1d" ,
updateDataPassEndDate = False,
forceCreateMarketData = False,
indexQuantCodeMap = indexQuantCodeMap, # required for quandl market data provider, defined above
# The Quandal provider used does not return Open, High, Low, Close, so map the "Adj Close" column
# to all standard columns in order to utilized some of the models that required that data (ATR, etc.)
create_std_ohlc_cols_dict = { "Open" : "Adj Close", "Low" : "Adj Close",
"High" : "Adj Close", "Close" : "Adj Close" }
)
ts_marketdat_mng_quandal.marketDataObj.getDataFrame()
brokerTradingObj = SimBrokerTrading()
tsConfDat = TradeStrategyConfigData()
# Set Config
tsConfDat.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "entry" : { 'votingPolicy' : 1, 'incNoInvestInVotingDec' : False,
'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
'lastn_match' : 1, 'cross_over_signal_for_trading' : False },
"exit" : { 'votingPolicy' : 1,
'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
'lastn_match' : 1 }
}
} )
# TS #1
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_1",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 20, 'win_slow' : 100 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #2
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_2",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 10, 'win_slow' : 50 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #3
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_3",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 10, 'win_slow' : 50 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #4
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_4",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 15, 'win_slow' : 60 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #5
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_5",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 15, 'win_slow' : 75 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #6
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_6",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 7, 'win_slow' : 35 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #7
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_7",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 12, 'win_slow' : 40 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #8
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_gru",
'actions_conf' : { "entry_exit" :
{ 'model' : "gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #9
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_lstm",
'actions_conf' : { "entry_exit" :
{ 'model' : "lstm",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #10
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_macd",
'actions_conf' : { "entry_exit" :
{ 'model' : "macd",
'type' : "ta",
'obj_args' : { 'window_slow' : 26, 'window_fast' : 12, 'window_sign' : 9,
'enter_long_macd_diff' : 0.5 , 'exi_long_macd_diff' : 0.5,
'enter_short_macd_diff' : -0.5, 'exi_short_macd_diff' : -0.5 },
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #11
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_rsi",
'actions_conf' : { "entry_exit" :
{ 'model' : "rsi",
'type' : "ta",
'obj_args' : { 'rsi_enter_long' : 30.0, 'rsi_exit_long' : 30.0,
'rsi_enter_short' : 70.0, 'rsi_exit_short' : 70.0 },
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
taRegItemGen = TradeAssetRegisterItemGenerator()
portf_registered_obj = taRegItemGen.createTARegItemForMarketDataMngs(
name_ta_reg_item = "Portfolio J",
# *** Trade Assets & Market Data Managers
market_data_mngs = { "yf" : [ portfolio_trade_assets_yf, ts_marketdat_mng_yf,
MarketDataPeriod.Day ],
"quandal" : [ portfolio_trade_assets_quandal, ts_marketdat_mng_quandal,
MarketDataPeriod.Day ],
"custom1" : [ portfolio_trade_assets_yf, ts_marketdat_mng_df,
MarketDataPeriod.Day ],
},
dirPathMarketData = dirPathMarketData,
# *** Broker
brokerTradingObj = brokerTradingObj,
# *** T.S. Permutations for each of the following sets of models
enter_exit_config_models = tsConfDat,
# *** Investment Manager Params
minPeriodsBetweenTrades = 1,
initInvestmentPerTradeStrategy = 2000000.0,
capPercentToInvestPerTrade = 100.0,
minInvestPercent = 5.0,
enter_trade_next_open_period = True,
min_account_balance = 1000.0,
portfRebalanceFreq = PortfolioRebalanceFrequency.Never,
portfRebalancePeriods = 1
)
print("Number of configured Trade Strategies: ", len(portf_registered_obj.taRegisterItems) )
training_period = DatasetDef(datasetType = DatasetType.Training,
strBegDateAIModels = "2001-07-01",
strBegDate = "2002-01-01",
strEndDate = "2006-12-31" )
validation_period = DatasetDef(datasetType = DatasetType.Validation,
strBegDateAIModels = "2006-07-01",
strBegDate = "2007-01-01",
strEndDate = "2008-12-31" )
testing_period = DatasetDef(datasetType = DatasetType.Testing,
strBegDateAIModels = "2008-07-01",
strBegDate = "2009-01-01",
strEndDate = "2009-12-31" )
fit_datasets = FitDatasetsDef( trainingDataset = training_period,
validationDataset = validation_period )
tsExecuteEngine = BacktestExecution( \
name = "Backtest for Portfolio J",
timePeriod = testing_period,
fitDatasets = fit_datasets,
trade_asset_registered_item = portf_registered_obj )
tsExecuteEngine.evaluate()
tsExecuteEngine.getSummaryMetrics().to_excel("Portfolio-J backtest-metrics.xlsx")
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']].\
query('TA_Reg_Name.str.contains("CHRIS")', engine='python')
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'model_type', 'trade_asset', 'Start Period', 'End Period', 'Time in Market ',
'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ]
Portfolio K: Long and Multiple Configured SMA Trade Strategies for US Indixes, with Stop Models
Description:
1. Seven distinct SMA Trade Strategies for enter/exit a trade, plus an ensemble trade strategy
of all seven SMA models
2. Eight different stop-models
1. Stop Loss order with specified stop-loss percent limit
2. Trail Stop Loss order with specified trail-stop-loss percent limit
3. Combine Stop-Loss & Trail-Stop-Loss order with specified percent limits
4-8. Five different Combine Stop-Loss & Trail-Stop-Loss models, configured with dynamic derived
stop-loss and trail-stop-loss percent limits using Average True Range(ATR) algorithm
3. $2,000,000/strategy
3. No-Rebalance during the backtest
4. 100% capital invested
5. Portfolio investment using equal weights for each trade strategy
Backtest:
1. Type: regular
2. Test Period:
1. Begin Date = 2001-01-01
2. End Date = 2020-12-31
portfolio_trade_assets = [ "^DJI", "^IXIC", "^GSPC" ]
dirPathMarketData = '../Data/US_Market_Indixes'
supportedTradeAssets = [ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
beg_date_str = "2000-01-01"
end_date_str = None
ts_marketdat_mng = TradeStrategyMarketDataMng(\
marketDataProviderName = "yahoofinance",
supportedTradeAssets = supportedTradeAssets,
stock_price_col_name = "Adj Close",
fileNameMarketData = "US_Indixes_And_ETFs_MrkData",
dirPathMarketData = dirPathMarketData,
beg_date_str = beg_date_str,
end_date_str = end_date_str,
forceCreateMarketData = False,
interval = "1d" )
brokerTradingObj = SimBrokerTrading()
tsConfDat = TradeStrategyConfigData()
# Set Config
tsConfDat.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "entry" : { 'votingPolicy' : 1, 'incNoInvestInVotingDec' : False,
'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
'lastn_match' : 1, 'cross_over_signal_for_trading' : False },
"exit" : { 'votingPolicy' : 1,
'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
'lastn_match' : 1 }
}
} )
# TS #1
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_1",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 20, 'win_slow' : 100 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #2
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_2",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 10, 'win_slow' : 50 } ,
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #3
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_3",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 10, 'win_slow' : 57 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #4
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_4",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 15, 'win_slow' : 60 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #5
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_5",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 15, 'win_slow' : 75 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #6
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_6",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 7, 'win_slow' : 35 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #7
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_7",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 12, 'win_slow' : 40 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# ***
# *** Configure Several Types of Stop Actions
# ***
# order_type = 1 ( Stop-Loss )
# order_type = 2 ( Trail-Stop-Loss )
# order_type = 3 ( Combine Stop-Loss & Trail-Stop-Loss )
#
# Stop Models :
# fixval { user-defined stop-loss-percent and/or trail-stop-loss-percent }
# atr { uses ATR model to dynamically determined the stop and trail stop loss percents }
# 1) *** Stop-Loss Order Type
tsStopsConfDat_Stop_Loss = TradeStrategyConfigData()
tsStopsConfDat_Stop_Loss.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "stop" : { 'order_type' : 1 } }
} )
tsStopsConfDat_Stop_Loss.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "sl_fixval",
'actions_conf' : { "stop" :
{ 'model' : "fixval",
'type' : "ta",
'obj_args' : { 'stop_loss_per' : 0.002, 'trail_stop_loss_per' : 0.005 },
},
},
} )
# 2) *** Trail-Stop-Loss Order Type
tsStopsConfDat_Trail_Stop_Loss = TradeStrategyConfigData()
tsStopsConfDat_Trail_Stop_Loss.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "stop" : { 'order_type' : 2} }
} )
tsStopsConfDat_Trail_Stop_Loss.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "tsl_fixval",
'actions_conf' : { "stop" :
{ 'model' : "fixval",
'type' : "ta",
'obj_args' : { 'stop_loss_per' : 0.002, 'trail_stop_loss_per' : 0.005 },
},
},
} )
# 3) *** Combine Stop-Loss & Trail-Stop-Loss Order Type - Using Fixed Values
tsStopsConfDat_Stop_Loss_And_Trail_SL_1 = TradeStrategyConfigData()
tsStopsConfDat_Stop_Loss_And_Trail_SL_1.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "stop" : { 'order_type' : 3 } }
} )
tsStopsConfDat_Stop_Loss_And_Trail_SL_1.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "sl_tsl_fixval",
'actions_conf' : { "stop" :
{ 'model' : "fixval",
'type' : "ta",
'obj_args' : { 'stop_loss_per' : 0.002, 'trail_stop_loss_per' : 0.005 },
},
},
} )
# 4) *** Combine Stop-Loss & Trail-Stop-Loss Order Type - Using Dynamic Values from ATR
tsStopsConfDat_Stop_Loss_And_Trail_SL_2 = TradeStrategyConfigData()
tsStopsConfDat_Stop_Loss_And_Trail_SL_2.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "stop" : { 'order_type' : 3 } }
} )
tsStopsConfDat_Stop_Loss_And_Trail_SL_2.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "sl_tsl_atr_1",
'actions_conf' : { "stop" :
{ 'model' : "atr",
'type' : "ta",
'obj_args' : { 'atr_mov_ave' : 14,
'stop_loss_mult' : 0.5,
'trail_stop_loss_mult' : 1.0,
'max_stop_loss_per' : 0.05,
'min_stop_loss_per' : 0.002,
'max_trail_stop_loss_per' : 0.05,
'min_trail_stop_loss_per' : 0.005,
},
},
},
} )
# 5) ***
tsStopsConfDat_Stop_Loss_And_Trail_SL_3 = TradeStrategyConfigData()
tsStopsConfDat_Stop_Loss_And_Trail_SL_3.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "stop" : { 'order_type' : 3 } }
} )
tsStopsConfDat_Stop_Loss_And_Trail_SL_3.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "sl_tsl_atr_2",
'actions_conf' : { "stop" :
{ 'model' : "atr",
'type' : "ta",
'obj_args' : { 'atr_mov_ave' : 7,
'stop_loss_mult' : 0.05,
'trail_stop_loss_mult' : 0.075,
},
},
},
} )
# 6) ***
tsStopsConfDat_Stop_Loss_And_Trail_SL_4 = TradeStrategyConfigData()
tsStopsConfDat_Stop_Loss_And_Trail_SL_4.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "stop" : { 'order_type' : 3 } }
} )
tsStopsConfDat_Stop_Loss_And_Trail_SL_4.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "sl_tsl_atr_3",
'actions_conf' : { "stop" :
{ 'model' : "atr",
'type' : "ta",
'obj_args' : { 'atr_mov_ave' : 7,
'stop_loss_mult' : 0.01,
'trail_stop_loss_mult' : 0.03,
},
},
},
} )
# 7) ***
tsStopsConfDat_Stop_Loss_And_Trail_SL_5 = TradeStrategyConfigData()
tsStopsConfDat_Stop_Loss_And_Trail_SL_5.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "stop" : { 'order_type' : 3 } }
} )
tsStopsConfDat_Stop_Loss_And_Trail_SL_5.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "sl_tsl_atr_4",
'actions_conf' : { "stop" :
{ 'model' : "atr",
'type' : "ta",
'obj_args' : { 'atr_mov_ave' : 7,
'stop_loss_mult' : 0.05,
'trail_stop_loss_mult' : 0.075,
'max_stop_loss_per' : 0.005,
'min_stop_loss_per' : 0.002,
'max_trail_stop_loss_per' : 0.005,
'min_trail_stop_loss_per' : 0.002,
},
},
},
} )
# 8) ***
tsStopsConfDat_Stop_Loss_And_Trail_SL_6 = TradeStrategyConfigData()
tsStopsConfDat_Stop_Loss_And_Trail_SL_6.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "stop" : { 'order_type' : 3 } }
} )
tsStopsConfDat_Stop_Loss_And_Trail_SL_6.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "sl_tsl_atr_5",
'actions_conf' : { "stop" :
{ 'model' : "atr",
'type' : "ta",
'obj_args' : { 'atr_mov_ave' : 7,
'stop_loss_mult' : 0.05,
'trail_stop_loss_mult' : 0.075,
'max_stop_loss_per' : 0.005,
'min_stop_loss_per' : 0.002,
'max_trail_stop_loss_per' : 0.01,
'min_trail_stop_loss_per' : 0.005,
},
},
},
} )
stopsConfDatList = [ tsStopsConfDat_Stop_Loss, tsStopsConfDat_Trail_Stop_Loss,
tsStopsConfDat_Stop_Loss_And_Trail_SL_1, tsStopsConfDat_Stop_Loss_And_Trail_SL_2,
tsStopsConfDat_Stop_Loss_And_Trail_SL_3, tsStopsConfDat_Stop_Loss_And_Trail_SL_4,
tsStopsConfDat_Stop_Loss_And_Trail_SL_5, tsStopsConfDat_Stop_Loss_And_Trail_SL_6
]
taRegItemGen = TradeAssetRegisterItemGenerator()
portf_registered_obj = taRegItemGen.createTARegItem(
name_ta_reg_item = "Portfolio K",
# *** Trade Assets & Market Data
portfolio_trade_assets = portfolio_trade_assets,
ts_marketdat_mng = ts_marketdat_mng,
dirPathMarketData = dirPathMarketData,
market_data_period = MarketDataPeriod.Day,
# *** Broker
brokerTradingObj = brokerTradingObj,
# *** T.S. Permutations for each of the following sets of models
enter_exit_config_models = tsConfDat,
stop_config_models = stopsConfDatList,
# *** Investment Manager Params
minPeriodsBetweenTrades = 1,
initInvestmentPerTradeStrategy = 2000000.0,
capPercentToInvestPerTrade = 100.0,
minInvestPercent = 5.0,
enter_trade_next_open_period = True,
min_account_balance = 1000.0,
portfRebalanceFreq = PortfolioRebalanceFrequency.Never,
portfRebalancePeriods = 1
)
print("Number of configured Trade Strategies: ", len(portf_registered_obj.taRegisterItems) )
tsExecuteEngine = BacktestExecution( \
name = "Backtest for Portfolio K",
timePeriod = DatasetDef(datasetType = DatasetType.Testing,
strBegDate = "2001-01-01",
strEndDate = "2020-12-31" ),
trade_asset_registered_item = portf_registered_obj )
tsExecuteEngine.evaluate()
tsExecuteEngine.getSummaryMetrics().to_excel("Portfolio-K backtest-metrics.xlsx")
DOW
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']].\
query('TA_Reg_Name.str.contains("DJI")', engine='python')
Nasdaq
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']].\
query('TA_Reg_Name.str.contains("IXIC")', engine='python')
S&P 500
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']].\
query('TA_Reg_Name.str.contains("GSPC")', engine='python')
Portfolio L: Long and Multiple Configured TA Trade Strategies for US Indixes, with Stop Models
Description:
1. Eleven distinct TA Trade Strategies for enter/exit a trade, plus an ensemble trade strategy
of all eleven TA models
2. Five different stop-models
1. Stop Loss order with specified stop-loss percent limit
2. Trail Stop Loss order with specified trail-stop-loss percent limit
3. Combine Stop-Loss & Trail-Stop-Loss order with specified percent limits
4-5. Three different Combine Stop-Loss & Trail-Stop-Loss models, configured with dynamic derived
stop-loss and trail-stop-loss percent limits using Average True Range(ATR) algorithm
3. $2,000,000/strategy
3. No-Rebalance during the backtest
4. 100% capital invested
5. Portfolio investment using equal weights for each trade strategy
Backtest:
1. Type: regular
2. Test Period:
1. Begin Date = 2001-01-01
2. End Date = 2020-12-31
portfolio_trade_assets = [ "^DJI", "^IXIC", "^GSPC" ]
dirPathMarketData = '../Data/US_Market_Indixes'
supportedTradeAssets = [ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
beg_date_str = "2000-01-01"
end_date_str = None
ts_marketdat_mng = TradeStrategyMarketDataMng(\
marketDataProviderName = "yahoofinance",
supportedTradeAssets = supportedTradeAssets,
stock_price_col_name = "Adj Close",
fileNameMarketData = "US_Indixes_And_ETFs_MrkData",
dirPathMarketData = dirPathMarketData,
beg_date_str = beg_date_str,
end_date_str = end_date_str,
forceCreateMarketData = False,
interval = "1d" )
brokerTradingObj = SimBrokerTrading()
tsConfDat = TradeStrategyConfigData()
# Set Config
tsConfDat.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "entry" : { 'votingPolicy' : 1, 'incNoInvestInVotingDec' : False,
'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
'lastn_match' : 1, 'cross_over_signal_for_trading' : False },
"exit" : { 'votingPolicy' : 1,
'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
'lastn_match' : 1 }
}
} )
# TS #1
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_1",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 10, 'win_slow' : 50 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #2
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_2",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 15, 'win_slow' : 60 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #3
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_bb",
'actions_conf' : { "entry_exit" :
{ 'model' : "bb",
'type' : "ta",
'obj_args' : { 'window' : 13, 'window_dev' : 1 } ,
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #4
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_macd",
'actions_conf' : { "entry_exit" :
{ 'model' : "macd",
'type' : "ta",
'obj_args' : { 'window_slow' : 26, 'window_fast' : 12, 'window_sign' : 9,
'enter_long_macd_diff' : 0.5 , 'exi_long_macd_diff' : 0.5,
'enter_short_macd_diff' : -0.5, 'exi_short_macd_diff' : -0.5 },
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #5
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_rsi",
'actions_conf' : { "entry_exit" :
{ 'model' : "rsi",
'type' : "ta",
'obj_args' : { 'rsi_enter_long' : 30.0, 'rsi_exit_long' : 30.0,
'rsi_enter_short' : 70.0, 'rsi_exit_short' : 70.0 },
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #6
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_srsi",
'actions_conf' : { "entry_exit" :
{ 'model' : "srsi",
'type' : "ta",
'obj_args' : { 'window' : 14, 'smooth1' : 3, 'smooth2' : 3,
'srsi_enter_long' : 0.8, 'srsi_exit_long' : 0.8,
'srsi_enter_short' : 0.2, 'srsi_exit_short' : 0.2 },
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #7
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_adx",
'actions_conf' : { "entry_exit" :
{ 'model' : "adx",
'type' : "ta",
'obj_args' : { 'window' : 14, 'adx_enter_long_ge' : 14, 'adx_exit_long_lt' : 14,
'adx_enter_short_ge' : 14, 'adx_exit_short_lt' : 14 },
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #8
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_kama",
'actions_conf' : { "entry_exit" :
{ 'model' : "kama",
'type' : "ta",
'obj_args' : { 'window_fast' : 10, 'pow1_fast' : 2, 'pow2_fast' : 30,
'window_slow' : 10, 'pow1_slow' : 5, 'pow2_slow' : 30 },
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #9
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_tsi",
'actions_conf' : { "entry_exit" :
{ 'model' : "tsi",
'type' : "ta",
'obj_args' : { 'window_slow' : 25, 'window_fast' : 5 },
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #10
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_forceindex",
'actions_conf' : { "entry_exit" :
{ 'model' : "forceindex",
'type' : "ta",
'obj_args' : { 'window' : 39 },
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #11
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_mfi",
'actions_conf' : { "entry_exit" :
{ 'model' : "mfi",
'type' : "ta",
'obj_args' : { 'window' : 14, 'long_slope_win' : 15, 'short_slope_win' : 15 },
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# ***
# *** Configure Several Types of Stop Actions
# ***
# order_type = 1 ( Stop-Loss )
# order_type = 2 ( Trail-Stop-Loss )
# order_type = 3 ( Combine Stop-Loss & Trail-Stop-Loss )
#
# Stop Models :
# fixval { user-defined stop-loss-percent and/or trail-stop-loss-percent }
# atr { uses ATR model to dynamically determined the stop and trail stop loss percents }
# *** Stop-Loss Order Type
tsStopsConfDat_Stop_Loss = TradeStrategyConfigData()
tsStopsConfDat_Stop_Loss.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "stop" : { 'order_type' : 1 } }
} )
tsStopsConfDat_Stop_Loss.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "sl_fixval",
'actions_conf' : { "stop" :
{ 'model' : "fixval",
'type' : "ta",
'obj_args' : { 'stop_loss_per' : 0.002, 'trail_stop_loss_per' : 0.005 },
},
},
} )
# *** Trail-Stop-Loss Order Type
tsStopsConfDat_Trail_Stop_Loss = TradeStrategyConfigData()
tsStopsConfDat_Trail_Stop_Loss.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "stop" : { 'order_type' : 2} }
} )
tsStopsConfDat_Trail_Stop_Loss.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "tsl_fixval",
'actions_conf' : { "stop" :
{ 'model' : "fixval",
'type' : "ta",
'obj_args' : { 'stop_loss_per' : 0.002, 'trail_stop_loss_per' : 0.005 },
},
},
} )
# *** Combine Stop-Loss & Trail-Stop-Loss Order Type - Using Fixed Values
tsStopsConfDat_Stop_Loss_And_Trail_SL_1 = TradeStrategyConfigData()
tsStopsConfDat_Stop_Loss_And_Trail_SL_1.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "stop" : { 'order_type' : 3 } }
} )
tsStopsConfDat_Stop_Loss_And_Trail_SL_1.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "sl_tsl_fixval",
'actions_conf' : { "stop" :
{ 'model' : "fixval",
'type' : "ta",
'obj_args' : { 'stop_loss_per' : 0.002, 'trail_stop_loss_per' : 0.005 },
},
},
} )
# ***
tsStopsConfDat_Stop_Loss_And_Trail_SL_3 = TradeStrategyConfigData()
tsStopsConfDat_Stop_Loss_And_Trail_SL_3.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "stop" : { 'order_type' : 3 } }
} )
tsStopsConfDat_Stop_Loss_And_Trail_SL_3.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "sl_tsl_atr_2",
'actions_conf' : { "stop" :
{ 'model' : "atr",
'type' : "ta",
'obj_args' : { 'atr_mov_ave' : 7,
'stop_loss_mult' : 0.05,
'trail_stop_loss_mult' : 0.075,
},
},
},
} )
# ***
tsStopsConfDat_Stop_Loss_And_Trail_SL_4 = TradeStrategyConfigData()
tsStopsConfDat_Stop_Loss_And_Trail_SL_4.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "stop" : { 'order_type' : 3 } }
} )
tsStopsConfDat_Stop_Loss_And_Trail_SL_4.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "sl_tsl_atr_3",
'actions_conf' : { "stop" :
{ 'model' : "atr",
'type' : "ta",
'obj_args' : { 'atr_mov_ave' : 7,
'stop_loss_mult' : 0.01,
'trail_stop_loss_mult' : 0.03,
},
},
},
} )
stopsConfDatList = [ tsStopsConfDat_Stop_Loss, tsStopsConfDat_Trail_Stop_Loss,
tsStopsConfDat_Stop_Loss_And_Trail_SL_1, tsStopsConfDat_Stop_Loss_And_Trail_SL_3,
tsStopsConfDat_Stop_Loss_And_Trail_SL_4
]
taRegItemGen = TradeAssetRegisterItemGenerator()
portf_registered_obj = taRegItemGen.createTARegItem(
name_ta_reg_item = "Portfolio L",
# *** Trade Assets & Market Data
portfolio_trade_assets = portfolio_trade_assets,
ts_marketdat_mng = ts_marketdat_mng,
dirPathMarketData = dirPathMarketData,
market_data_period = MarketDataPeriod.Day,
# *** Broker
brokerTradingObj = brokerTradingObj,
# *** T.S. Permutations for each of the following sets of models
enter_exit_config_models = tsConfDat,
stop_config_models = stopsConfDatList,
# *** Investment Manager Params
minPeriodsBetweenTrades = 1,
initInvestmentPerTradeStrategy = 2000000.0,
capPercentToInvestPerTrade = 100.0,
minInvestPercent = 5.0,
enter_trade_next_open_period = True,
min_account_balance = 1000.0,
portfRebalanceFreq = PortfolioRebalanceFrequency.Never,
portfRebalancePeriods = 1
)
print("Number of configured Trade Strategies: ", len(portf_registered_obj.taRegisterItems) )
tsExecuteEngine = BacktestExecution( \
name = "Backtest for Portfolio L",
timePeriod = DatasetDef(datasetType = DatasetType.Testing,
strBegDate = "2001-01-01",
strEndDate = "2020-12-31" ),
trade_asset_registered_item = portf_registered_obj )
tsExecuteEngine.evaluate()
tsExecuteEngine.getSummaryMetrics().to_excel("Portfolio-L backtest-metrics.xlsx")
DOW
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']].\
query('TA_Reg_Name.str.contains("DJI")', engine='python')
Nasdaq
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']].\
query('TA_Reg_Name.str.contains("IXIC")', engine='python')
S&P 500
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']].\
query('TA_Reg_Name.str.contains("GSPC")', engine='python')
Portfolio M: Long and Multiple Configured AI Trade Strategies for US Indixes, with Stop Models
Description:
1. Eight distinct AI Trade Strategies for enter/exit a trade, plus an ensemble trade strategy
of all AI models
2. Four different stop-models
1. Combine Stop-Loss & Trail-Stop-Loss order with specified percent limits
2-4. Three different Combine Stop-Loss & Trail-Stop-Loss models, configured with dynamic derived
stop-loss and trail-stop-loss percent limits using Average True Range(ATR) algorithm
3. $2,000,000/strategy
3. No-Rebalance during the backtest
4. 100% capital invested
5. Portfolio investment using equal weights for each trade strategy
Backtest:
1. Type: regular
2. AI Models Fit Date Ranges
1. Training Period:
1. Begin Date = 2002-01-01
2. End Date = 2006-12-31
2. Validation Period:
1. Begin Date = 2007-01-01
2. End Date = 2008-12-31
4. Test Period:
1. Begin Date = 2009-01-01
2. End Date = 2009-12-31
portfolio_trade_assets = [ "^DJI", "^IXIC", "^GSPC" ]
dirPathMarketData = '../Data/US_Market_Indixes'
supportedTradeAssets = [ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
beg_date_str = "2000-01-01"
end_date_str = None
ts_marketdat_mng = TradeStrategyMarketDataMng(\
marketDataProviderName = "yahoofinance",
supportedTradeAssets = supportedTradeAssets,
stock_price_col_name = "Adj Close",
fileNameMarketData = "US_Indixes_And_ETFs_MrkData",
dirPathMarketData = dirPathMarketData,
beg_date_str = beg_date_str,
end_date_str = end_date_str,
forceCreateMarketData = False,
interval = "1d" )
brokerTradingObj = SimBrokerTrading()
tsConfDat = TradeStrategyConfigData()
# Set Config
tsConfDat.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "entry" : { 'votingPolicy' : 1, 'incNoInvestInVotingDec' : False,
'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
'lastn_match' : 1, 'cross_over_signal_for_trading' : False },
"exit" : { 'votingPolicy' : 1,
'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
'lastn_match' : 1 }
}
} )
# TS #1
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_gru_1",
'actions_conf' : { "entry_exit" :
{ 'model' : "gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #2
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_lstm",
'actions_conf' : { "entry_exit" :
{ 'model' : "lstm",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #3
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_conv1d_gru",
'actions_conf' : { "entry_exit" :
{ 'model' : "conv1d_gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #4
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_conv1d_lstm",
'actions_conf' : { "entry_exit" :
{ 'model' : "conv1d_lstm",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #5
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_wavenet",
'actions_conf' : { "entry_exit" :
{ 'model' : "wavenet",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #6
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_wavenet_gru",
'actions_conf' : { "entry_exit" :
{ 'model' : "wavenet_gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #7
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_wavenet_lstm",
'actions_conf' : { "entry_exit" :
{ 'model' : "wavenet_lstm",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #8
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_gru_2",
'actions_conf' : { "entry_exit" :
{ 'model' : "gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 40, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 3,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# ***
# *** Configure Several Types of Stop Actions
# ***
# order_type = 1 ( Stop-Loss )
# order_type = 2 ( Trail-Stop-Loss )
# order_type = 3 ( Combine Stop-Loss & Trail-Stop-Loss )
#
# Stop Models :
# fixval { user-defined stop-loss-percent and/or trail-stop-loss-percent }
# atr { uses ATR model to dynamically determined the stop and trail stop loss percents }
# *** Combine Stop-Loss & Trail-Stop-Loss Order Type - Using Fixed Values
tsStopsConfDat_Stop_Loss_And_Trail_SL_1 = TradeStrategyConfigData()
tsStopsConfDat_Stop_Loss_And_Trail_SL_1.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "stop" : { 'order_type' : 3 } }
} )
tsStopsConfDat_Stop_Loss_And_Trail_SL_1.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "sl_tsl_fixval",
'actions_conf' : { "stop" :
{ 'model' : "fixval",
'type' : "ta",
'obj_args' : { 'stop_loss_per' : 0.002, 'trail_stop_loss_per' : 0.005 },
},
},
} )
# *** Combine Stop-Loss & Trail-Stop-Loss Order Type - Using Dynamic Values from ATR
tsStopsConfDat_Stop_Loss_And_Trail_SL_2 = TradeStrategyConfigData()
tsStopsConfDat_Stop_Loss_And_Trail_SL_2.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "stop" : { 'order_type' : 3 } }
} )
tsStopsConfDat_Stop_Loss_And_Trail_SL_2.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "sl_tsl_atr_1",
'actions_conf' : { "stop" :
{ 'model' : "atr",
'type' : "ta",
'obj_args' : { 'atr_mov_ave' : 14,
'stop_loss_mult' : 0.5,
'trail_stop_loss_mult' : 1.0,
'max_stop_loss_per' : 0.05,
'min_stop_loss_per' : 0.002,
'max_trail_stop_loss_per' : 0.05,
'min_trail_stop_loss_per' : 0.005,
},
},
},
} )
# ***
tsStopsConfDat_Stop_Loss_And_Trail_SL_3 = TradeStrategyConfigData()
tsStopsConfDat_Stop_Loss_And_Trail_SL_3.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "stop" : { 'order_type' : 3 } }
} )
tsStopsConfDat_Stop_Loss_And_Trail_SL_3.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "sl_tsl_atr_2",
'actions_conf' : { "stop" :
{ 'model' : "atr",
'type' : "ta",
'obj_args' : { 'atr_mov_ave' : 7,
'stop_loss_mult' : 0.05,
'trail_stop_loss_mult' : 0.075,
},
},
},
} )
# ***
tsStopsConfDat_Stop_Loss_And_Trail_SL_4 = TradeStrategyConfigData()
tsStopsConfDat_Stop_Loss_And_Trail_SL_4.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "stop" : { 'order_type' : 3 } }
} )
tsStopsConfDat_Stop_Loss_And_Trail_SL_4.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "sl_tsl_atr_3",
'actions_conf' : { "stop" :
{ 'model' : "atr",
'type' : "ta",
'obj_args' : { 'atr_mov_ave' : 7,
'stop_loss_mult' : 0.01,
'trail_stop_loss_mult' : 0.03,
},
},
},
} )
stopsConfDatList = [ tsStopsConfDat_Stop_Loss_And_Trail_SL_1, tsStopsConfDat_Stop_Loss_And_Trail_SL_2,
tsStopsConfDat_Stop_Loss_And_Trail_SL_3, tsStopsConfDat_Stop_Loss_And_Trail_SL_4,
]
taRegItemGen = TradeAssetRegisterItemGenerator()
portf_registered_obj = taRegItemGen.createTARegItem(
name_ta_reg_item = "Portfolio M",
# *** Trade Assets & Market Data
portfolio_trade_assets = portfolio_trade_assets,
ts_marketdat_mng = ts_marketdat_mng,
dirPathMarketData = dirPathMarketData,
market_data_period = MarketDataPeriod.Day,
# *** Broker
brokerTradingObj = brokerTradingObj,
# *** T.S. Permutations for each of the following sets of models
enter_exit_config_models = tsConfDat,
stop_config_models = stopsConfDatList,
# *** Investment Manager Params
minPeriodsBetweenTrades = 1,
initInvestmentPerTradeStrategy = 2000000.0,
capPercentToInvestPerTrade = 100.0,
minInvestPercent = 5.0,
enter_trade_next_open_period = True,
min_account_balance = 1000.0,
portfRebalanceFreq = PortfolioRebalanceFrequency.Never,
portfRebalancePeriods = 1
)
print("Number of configured Trade Strategies: ", len(portf_registered_obj.taRegisterItems) )
training_period = DatasetDef(datasetType = DatasetType.Training,
strBegDateAIModels = "2001-07-01",
strBegDate = "2002-01-01",
strEndDate = "2006-12-31" )
validation_period = DatasetDef(datasetType = DatasetType.Validation,
strBegDateAIModels = "2006-07-01",
strBegDate = "2007-01-01",
strEndDate = "2008-12-31" )
testing_period = DatasetDef(datasetType = DatasetType.Testing,
strBegDateAIModels = "2008-07-01",
strBegDate = "2009-01-01",
strEndDate = "2009-12-31" )
fit_datasets = FitDatasetsDef( trainingDataset = training_period,
validationDataset = validation_period )
tsExecuteEngine = BacktestExecution( \
name = "Backtest for Portfolio M",
timePeriod = testing_period,
fitDatasets = fit_datasets,
trade_asset_registered_item = portf_registered_obj )
tsExecuteEngine.evaluate()
tsExecuteEngine.getSummaryMetrics().to_excel("Portfolio-M backtest-metrics.xlsx")
DOW
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']].\
query('TA_Reg_Name.str.contains("DJI")', engine='python')
Nasdaq
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']].\
query('TA_Reg_Name.str.contains("IXIC")', engine='python')
S&P 500
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']].\
query('TA_Reg_Name.str.contains("GSPC")', engine='python')
Portfolio N: Long and Multiple Configured AI Trade Strategies for US Indixes, with Stop Models
Description:
1. Eight distinct AI Trade Strategies for enter/exit a trade, plus an ensemble trade strategy
of all AI models
2. Five different stop-models
Different Combine Stop-Loss & Trail-Stop-Loss models, configured with AI derived
stop-loss and trail-stop-loss percent limits using LSTM, GRU, etc. time series models to
forecast next day True Range for the stock, and use that information to derive the percent
stop limits.
The Stop-Models in this Portfolio are AI based, unlike the ones in Portfolio K, which are
based on the Technical Indicator, Average True Range (ATR)
3. $2,000,000/strategy
3. No-Rebalance during the backtest
4. 100% capital invested
5. Portfolio investment using equal weights for each trade strategy
Backtest:
1. Type: regular
2. AI Models Fit Date Ranges
1. Training Period:
1. Begin Date = 2002-01-01
2. End Date = 2006-12-31
2. Validation Period:
1. Begin Date = 2007-01-01
2. End Date = 2008-12-31
4. Test Period:
1. Begin Date = 2009-01-01
2. End Date = 2009-12-31
portfolio_trade_assets = [ "^DJI", "^IXIC", "^GSPC" ]
dirPathMarketData = '../Data/US_Market_Indixes'
supportedTradeAssets = [ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
beg_date_str = "2000-01-01"
end_date_str = None
ts_marketdat_mng = TradeStrategyMarketDataMng(\
marketDataProviderName = "yahoofinance",
supportedTradeAssets = supportedTradeAssets,
stock_price_col_name = "Adj Close",
fileNameMarketData = "US_Indixes_And_ETFs_MrkData",
dirPathMarketData = dirPathMarketData,
beg_date_str = beg_date_str,
end_date_str = end_date_str,
forceCreateMarketData = False,
interval = "1d" )
brokerTradingObj = SimBrokerTrading()
tsConfDat = TradeStrategyConfigData()
# Set Config
tsConfDat.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "entry" : { 'votingPolicy' : 1, 'incNoInvestInVotingDec' : False,
'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
'lastn_match' : 1, 'cross_over_signal_for_trading' : False },
"exit" : { 'votingPolicy' : 1,
'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
'lastn_match' : 1 }
}
} )
# TS #1
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_gru_1",
'actions_conf' : { "entry_exit" :
{ 'model' : "gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #2
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_lstm",
'actions_conf' : { "entry_exit" :
{ 'model' : "lstm",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #3
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_conv1d_gru",
'actions_conf' : { "entry_exit" :
{ 'model' : "conv1d_gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #4
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_conv1d_lstm",
'actions_conf' : { "entry_exit" :
{ 'model' : "conv1d_lstm",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #5
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_wavenet",
'actions_conf' : { "entry_exit" :
{ 'model' : "wavenet",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #6
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_wavenet_gru",
'actions_conf' : { "entry_exit" :
{ 'model' : "wavenet_gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #7
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_wavenet_lstm",
'actions_conf' : { "entry_exit" :
{ 'model' : "wavenet_lstm",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #8
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_gru_2",
'actions_conf' : { "entry_exit" :
{ 'model' : "gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 40, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 3,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
##### ***
# *** Configure Several Types of Stop Actions
# ***
# order_type = 1 ( Stop-Loss )
# order_type = 2 ( Trail-Stop-Loss )
# order_type = 3 ( Combine Stop-Loss & Trail-Stop-Loss )
#
# Stop Models :
# ai_true_range { - uses an AI model to predict the next's day True-Range, the underlying
# predicting AI Model can vary, in this example, two models use LSTM, and
# another one uses xxx.
# - the ai_true_range model applies rules and constraints to the predicted true
# range, and derives the stop_loss and trail_stop_loss percent limits for the trade.
# }
ai_model_x_features = ['Adj Close', 'Volume', 'true_range', 'true_range_vol1' ]
# AI Stop Model #1 (using LSTM for predicting next day True Range)
tsStopsConfDat_Stop_Loss_And_Trail_SL_1 = TradeStrategyConfigData()
tsStopsConfDat_Stop_Loss_And_Trail_SL_1.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "stop" : { 'order_type' : 3 } }
} )
tsStopsConfDat_Stop_Loss_And_Trail_SL_1.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "sl_tsl_ai_tr_1",
'actions_conf' : { "stop" :
{ 'model' : "ai_true_range",
'ai_model' : "gru",
'type' : "ai",
'obj_args' : { 'stop_loss_mult' : 0.05,
'trail_stop_loss_mult' : 0.075,
'max_stop_loss_per' : 0.05,
'min_stop_loss_per' : 0.0001,
'max_trail_stop_loss_per' : 0.07,
'min_trail_stop_loss_per' : 0.0001,
},
'ai_obj_args' : { 'n_steps' : 5, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 1,
'epochs' : 20,
'features' : ai_model_x_features,
'features_label' : 'true_range'
}
},
},
} )
# AI Stop Model #2 (using LSTM for predicting next day True Range)
# -> diff, stop loss and trail loss multiplier, slightly smaller than model #1
tsStopsConfDat_Stop_Loss_And_Trail_SL_2 = TradeStrategyConfigData()
tsStopsConfDat_Stop_Loss_And_Trail_SL_2.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "stop" : { 'order_type' : 3 } }
} )
tsStopsConfDat_Stop_Loss_And_Trail_SL_2.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "sl_tsl_ai_tr_2",
'actions_conf' : { "stop" :
{ 'model' : "ai_true_range",
'ai_model' : "lstm",
'type' : "ai",
'obj_args' : { 'stop_loss_mult' : 0.01,
'trail_stop_loss_mult' : 0.03,
'max_stop_loss_per' : 0.05,
'min_stop_loss_per' : 0.0001,
'max_trail_stop_loss_per' : 0.07,
'min_trail_stop_loss_per' : 0.0001,
},
'ai_obj_args' : { 'n_steps' : 10, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 3,
'epochs' : 20,
'features' : ai_model_x_features,
'features_label' : 'true_range'
}
},
},
} )
# AI Stop Model #3 (using LSTM for predicting next day True Range)
# -> diff, stop loss and trail loss multiplier, bigger than model #1 and #2
tsStopsConfDat_Stop_Loss_And_Trail_SL_3 = TradeStrategyConfigData()
tsStopsConfDat_Stop_Loss_And_Trail_SL_3.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "stop" : { 'order_type' : 3 } }
} )
tsStopsConfDat_Stop_Loss_And_Trail_SL_3.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "sl_tsl_ai_tr_3",
'actions_conf' : { "stop" :
{ 'model' : "ai_true_range",
'ai_model' : "lstm",
'type' : "ai",
'obj_args' : { 'stop_loss_mult' : 0.1,
'trail_stop_loss_mult' : 0.125,
'max_stop_loss_per' : 0.05,
'min_stop_loss_per' : 0.0001,
'max_trail_stop_loss_per' : 0.07,
'min_trail_stop_loss_per' : 0.0001,
},
'ai_obj_args' : { 'n_steps' : 10, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 3,
'epochs' : 20,
'features' : ai_model_x_features,
'features_label' : 'true_range'
}
},
},
} )
# AI Stop Model #4 (using conv1d_gru for predicting next day True Range)
# -> diff, stop loss and trail loss multiplier, bigger than model #1 and #2
tsStopsConfDat_Stop_Loss_And_Trail_SL_4 = TradeStrategyConfigData()
tsStopsConfDat_Stop_Loss_And_Trail_SL_4.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "stop" : { 'order_type' : 3 } }
} )
tsStopsConfDat_Stop_Loss_And_Trail_SL_4.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "sl_tsl_ai_tr_4",
'actions_conf' : { "stop" :
{ 'model' : "ai_true_range",
'ai_model' : "conv1d_gru",
'type' : "ai",
'obj_args' : { 'stop_loss_mult' : 0.01,
'trail_stop_loss_mult' : 0.03,
'max_stop_loss_per' : 0.05,
'min_stop_loss_per' : 0.0001,
'max_trail_stop_loss_per' : 0.07,
'min_trail_stop_loss_per' : 0.0001,
},
'ai_obj_args' : { 'n_steps' : 20, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 3,
'epochs' : 20,
'features' : ai_model_x_features,
'features_label' : 'true_range'
}
},
},
} )
# AI Stop Model #5 (using conv1d_gru for predicting next day True Range)
# -> diff, stop loss and trail loss multiplier, bigger than model #1 and #2
tsStopsConfDat_Stop_Loss_And_Trail_SL_5 = TradeStrategyConfigData()
tsStopsConfDat_Stop_Loss_And_Trail_SL_5.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "stop" : { 'order_type' : 3 } }
} )
tsStopsConfDat_Stop_Loss_And_Trail_SL_5.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "sl_tsl_ai_tr_5",
'actions_conf' : { "stop" :
{ 'model' : "ai_true_range",
'ai_model' : "wavenet",
'type' : "ai",
'obj_args' : { 'stop_loss_mult' : 0.03,
'trail_stop_loss_mult' : 0.05,
'max_stop_loss_per' : 0.05,
'min_stop_loss_per' : 0.0001,
'max_trail_stop_loss_per' : 0.07,
'min_trail_stop_loss_per' : 0.0001,
},
'ai_obj_args' : { 'n_steps' : 20, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 3,
'epochs' : 20,
'features' : ai_model_x_features,
'features_label' : 'true_range'
}
},
},
} )
stopsConfDatList = [ tsStopsConfDat_Stop_Loss_And_Trail_SL_1, tsStopsConfDat_Stop_Loss_And_Trail_SL_2,
tsStopsConfDat_Stop_Loss_And_Trail_SL_3, tsStopsConfDat_Stop_Loss_And_Trail_SL_4,
tsStopsConfDat_Stop_Loss_And_Trail_SL_5 ]
taRegItemGen = TradeAssetRegisterItemGenerator()
portf_registered_obj = taRegItemGen.createTARegItem(
name_ta_reg_item = "Portfolio N",
# *** Trade Assets & Market Data
portfolio_trade_assets = portfolio_trade_assets,
ts_marketdat_mng = ts_marketdat_mng,
dirPathMarketData = dirPathMarketData,
market_data_period = MarketDataPeriod.Day,
# *** Broker
brokerTradingObj = brokerTradingObj,
# *** T.S. Permutations for each of the following sets of models
enter_exit_config_models = tsConfDat,
stop_config_models = stopsConfDatList,
# *** Investment Manager Params
minPeriodsBetweenTrades = 1,
initInvestmentPerTradeStrategy = 2000000.0,
capPercentToInvestPerTrade = 100.0,
minInvestPercent = 5.0,
enter_trade_next_open_period = True,
min_account_balance = 1000.0,
portfRebalanceFreq = PortfolioRebalanceFrequency.Never,
portfRebalancePeriods = 1
)
print("Number of configured Trade Strategies: ", len(portf_registered_obj.taRegisterItems) )
training_period = DatasetDef(datasetType = DatasetType.Training,
strBegDateAIModels = "2001-07-01",
strBegDate = "2002-01-01",
strEndDate = "2006-12-31" )
validation_period = DatasetDef(datasetType = DatasetType.Validation,
strBegDateAIModels = "2006-07-01",
strBegDate = "2007-01-01",
strEndDate = "2008-12-31" )
testing_period = DatasetDef(datasetType = DatasetType.Testing,
strBegDateAIModels = "2008-07-01",
strBegDate = "2009-01-01",
strEndDate = "2009-12-31" )
fit_datasets = FitDatasetsDef( trainingDataset = training_period,
validationDataset = validation_period )
tsExecuteEngine = BacktestExecution( \
name = "Backtest for Portfolio N",
timePeriod = testing_period,
fitDatasets = fit_datasets,
trade_asset_registered_item = portf_registered_obj )
tsExecuteEngine.evaluate()
tsExecuteEngine.getSummaryMetrics().to_excel("Portfolio-N backtest-metrics.xlsx")
DOW
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']].\
query('TA_Reg_Name.str.contains("DJI")', engine='python')
Nasdaq
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']].\
query('TA_Reg_Name.str.contains("IXIC")', engine='python')
S&P 500
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']].\
query('TA_Reg_Name.str.contains("GSPC")', engine='python')
tsExecuteEngine.getTradesTransactionDetailsDF().to_excel("portf_N_trades_transaction_details.xlsx")
A type of backtests that are designed to simulate fitting AI Models to different date ranges or to shift the date ranges for a backtest through time.
- Description :
- Re-fit the AI models that a given trade strategy depends on during a backtest
- Scenario:
- Given the following initial setting for a backtest:
AI Models Fit Date Ranges
1. Training Period:
1. Begin Date = 2001-01-01
2. End Date = 2005-12-31
2. Validation Period:
1. Begin Date = 2006-01-01
2. End Date = 2007-06-30
Test Period:
1. Begin Date = 2008-01-01
2. End Date = 2008-12-31
- Re-fit the models after the backtest has executed for a period (n days, n weeks, n months), by
either shifting the Training and Validation period or extending, that is anchoring the Training
Period start date
Example 1
1. Training Period:
1. Begin Date = 2001-01-01
2. End Date = 2005-12-31
2. Validation Period:
1. Begin Date = 2006-01-01
2. End Date = 2007-06-30
1. Training Period:
1. Begin Date = 2001-04-01
2. End Date = 2006-03-31
2. Validation Period:
1. Begin Date = 2006-04-01
2. End Date = 2007-09-30
Example 2
1. Training Period:
1. Begin Date = 2001-01-01
2. End Date = 2005-12-31
2. Validation Period:
1. Begin Date = 2006-01-01
2. End Date = 2007-06-30
1. Training Period:
1. Begin Date = 2001-01-01
2. End Date = 2006-03-31
2. Validation Period:
1. Begin Date = 2006-04-01
2. End Date = 2007-09-30
...
Description:
Backtest:
1. Type: WFA Backtest
2. AI Models Fit Date Ranges
1. Training Period:
1. Begin Date = 2000-01-01
2. End Date = 2005-12-31
2. Validation Period:
1. Begin Date = 2006-01-01
2. End Date = 2007-12-31
4. Test Period:
1. Begin Date = 2008-01-01
2. End Date = 2008-12-31
portfolio_trade_assets = [ "^DJI", "^IXIC", "^GSPC" ]
dirPathMarketData = '../Data/US_Market_Indixes'
supportedTradeAssets = [ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
beg_date_str = "1980-01-01"
end_date_str = None
ts_marketdat_mng = TradeStrategyMarketDataMng(\
marketDataProviderName = "yahoofinance",
supportedTradeAssets = supportedTradeAssets,
stock_price_col_name = "Adj Close",
fileNameMarketData = "US_Indixes_And_ETFs_MrkData_From_1980",
dirPathMarketData = dirPathMarketData,
beg_date_str = beg_date_str,
end_date_str = end_date_str,
forceCreateMarketData = False,
interval = "1d" )
MarketData.getDateRangesForStocks( ts_marketdat_mng.marketDataObj.getDataFrame() )
brokerTradingObj = SimBrokerTrading()
tsConfDat = TradeStrategyConfigData()
# Set Config
tsConfDat.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "entry" : { 'votingPolicy' : 1, 'incNoInvestInVotingDec' : False,
'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
'lastn_match' : 1, 'cross_over_signal_for_trading' : False },
"exit" : { 'votingPolicy' : 1,
'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
'lastn_match' : 1 }
}
} )
# TS #1
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_gru_1",
'actions_conf' : { "entry_exit" :
{ 'model' : "gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #2
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_lstm",
'actions_conf' : { "entry_exit" :
{ 'model' : "lstm",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #3
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_conv1d_gru",
'actions_conf' : { "entry_exit" :
{ 'model' : "conv1d_gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #4
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_conv1d_lstm",
'actions_conf' : { "entry_exit" :
{ 'model' : "conv1d_lstm",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #5
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_wavenet",
'actions_conf' : { "entry_exit" :
{ 'model' : "wavenet",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #6
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_wavenet_gru",
'actions_conf' : { "entry_exit" :
{ 'model' : "wavenet_gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #7
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_wavenet_lstm",
'actions_conf' : { "entry_exit" :
{ 'model' : "wavenet_lstm",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #8
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_gru_2",
'actions_conf' : { "entry_exit" :
{ 'model' : "gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 40, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 3,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
taRegItemGen = TradeAssetRegisterItemGenerator()
portf_registered_obj = taRegItemGen.createTARegItem(
name_ta_reg_item = "WFA-Backtest 1",
# *** Trade Assets & Market Data
portfolio_trade_assets = portfolio_trade_assets,
ts_marketdat_mng = ts_marketdat_mng,
dirPathMarketData = dirPathMarketData,
market_data_period = MarketDataPeriod.Day,
# *** Broker
brokerTradingObj = brokerTradingObj,
# *** T.S. Permutations for each of the following sets of models
enter_exit_config_models = tsConfDat,
# *** Investment Manager Params
minPeriodsBetweenTrades = 1,
initInvestmentPerTradeStrategy = 2000000.0,
capPercentToInvestPerTrade = 100.0,
minInvestPercent = 5.0,
enter_trade_next_open_period = True,
min_account_balance = 1000.0,
portfRebalanceFreq = PortfolioRebalanceFrequency.Never,
portfRebalancePeriods = 1
)
print("Number of configured Trade Strategies: ", len(portf_registered_obj.taRegisterItems) )
training_period = DatasetDef(datasetType = DatasetType.Training,
strBegDateAIModels = "1999-07-01",
strBegDate = "2000-01-01",
strEndDate = "2005-12-31" )
validation_period = DatasetDef(datasetType = DatasetType.Validation,
strBegDateAIModels = "2005-07-01",
strBegDate = "2006-01-01",
strEndDate = "2007-12-31" )
testing_period = DatasetDef(datasetType = DatasetType.Testing,
strBegDateAIModels = "2007-07-01",
strBegDate = "2008-01-01",
strEndDate = "2008-12-31" )
fit_datasets = FitDatasetsDef( trainingDataset = training_period,
validationDataset = validation_period )
tsExecuteEngine = BacktestExecutionWFA( \
name = "WFA-Backtest 1",
test_period = testing_period,
fit_datasets_start = fit_datasets,
trade_asset_registered_item = portf_registered_obj,
wfa_slide_win_size = 4,
wfa_slide_win_period = WFASlideWindowPeriod.Months,
anchor_fit_dataset = False )
tsExecuteEngine.evaluate()
tsExecuteEngine.getSummaryMetrics().to_excel("WFA-Backtest-1 backtest-metrics.xlsx")
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']]
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'trade_asset', 'order_type',
'enter_num_models', 'enter_model', 'enter_model_type',
'exit_num_models', 'exit_model', 'exit_model_type',
'stop_model', 'stop_model_type',
'Start Period', 'End Period',
'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ]
Description:
Backtest:
1. Type: WFA Backtest
2. AI Models Fit Date Ranges
1. Training Period:
1. Begin Date = 2000-01-01
2. End Date = 2005-12-31
2. Validation Period:
1. Begin Date = 2006-01-01
2. End Date = 2007-12-31
4. Test Period:
1. Begin Date = 2008-01-01
2. End Date = 2010-12-31
portfolio_trade_assets = [ "^DJI", "^IXIC", "^GSPC" ]
dirPathMarketData = '../Data/US_Market_Indixes'
supportedTradeAssets = [ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
beg_date_str = "1980-01-01"
end_date_str = None
ts_marketdat_mng = TradeStrategyMarketDataMng(\
marketDataProviderName = "yahoofinance",
supportedTradeAssets = supportedTradeAssets,
stock_price_col_name = "Adj Close",
fileNameMarketData = "US_Indixes_And_ETFs_MrkData_From_1980",
dirPathMarketData = dirPathMarketData,
beg_date_str = beg_date_str,
end_date_str = end_date_str,
forceCreateMarketData = False,
interval = "1d" )
brokerTradingObj = SimBrokerTrading()
tsConfDat = TradeStrategyConfigData()
# Set Config
tsConfDat.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "entry" : { 'votingPolicy' : 1, 'incNoInvestInVotingDec' : False,
'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
'lastn_match' : 1, 'cross_over_signal_for_trading' : False },
"exit" : { 'votingPolicy' : 1,
'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
'lastn_match' : 1 }
}
} )
# TS #1
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_gru_1",
'actions_conf' : { "entry_exit" :
{ 'model' : "gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
"stop_lost" :
{ 'model' : "fix_perc",
'type' : "ta",
'obj_args' : { 'long_stop_los_per' : 5, 'short_stop_los_per' : 5 } }
},
} )
# TS #2
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_lstm",
'actions_conf' : { "entry_exit" :
{ 'model' : "lstm",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #3
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_conv1d_gru",
'actions_conf' : { "entry_exit" :
{ 'model' : "conv1d_gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #8
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_gru_2",
'actions_conf' : { "entry_exit" :
{ 'model' : "gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 40, 'no_neurons_lay1' : 30,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 3,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #10
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_2",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 15, 'win_slow' : 60 } ,
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #16
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_kama",
'actions_conf' : { "entry_exit" :
{ 'model' : "kama",
'type' : "ta",
'obj_args' : { 'window_fast' : 10, 'pow1_fast' : 2, 'pow2_fast' : 30,
'window_slow' : 10, 'pow1_slow' : 5, 'pow2_slow' : 30 },
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #17
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_tsi",
'actions_conf' : { "entry_exit" :
{ 'model' : "tsi",
'type' : "ta",
'obj_args' : { 'window_slow' : 25, 'window_fast' : 5 },
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
taRegItemGen = TradeAssetRegisterItemGenerator()
portf_registered_obj = taRegItemGen.createTARegItem(
name_ta_reg_item = "WFA-Backtest 2",
# *** Trade Assets & Market Data
portfolio_trade_assets = portfolio_trade_assets,
ts_marketdat_mng = ts_marketdat_mng,
dirPathMarketData = dirPathMarketData,
market_data_period = MarketDataPeriod.Day,
# *** Broker
brokerTradingObj = brokerTradingObj,
# *** T.S. Permutations for each of the following sets of models
enter_exit_config_models = tsConfDat,
# *** Investment Manager Params
minPeriodsBetweenTrades = 1,
initInvestmentPerTradeStrategy = 2000000.0,
capPercentToInvestPerTrade = 100.0,
minInvestPercent = 5.0,
enter_trade_next_open_period = True,
min_account_balance = 1000.0,
portfRebalanceFreq = PortfolioRebalanceFrequency.Never,
portfRebalancePeriods = 1
)
print("Number of configured Trade Strategies: ", len(portf_registered_obj.taRegisterItems) )
training_period = DatasetDef(datasetType = DatasetType.Training,
strBegDateAIModels = "1999-07-01",
strBegDate = "2000-01-01",
strEndDate = "2005-12-31" )
validation_period = DatasetDef(datasetType = DatasetType.Validation,
strBegDateAIModels = "2005-07-01",
strBegDate = "2006-01-01",
strEndDate = "2007-12-31" )
testing_period = DatasetDef(datasetType = DatasetType.Testing,
strBegDateAIModels = "2007-07-01",
strBegDate = "2008-01-01",
strEndDate = "2010-12-31" )
fit_datasets = FitDatasetsDef( trainingDataset = training_period,
validationDataset = validation_period )
tsExecuteEngine = BacktestExecutionWFA( \
name = "WFA-Backtest 2",
test_period = testing_period,
fit_datasets_start = fit_datasets,
trade_asset_registered_item = portf_registered_obj,
wfa_slide_win_size = 6,
wfa_slide_win_period = WFASlideWindowPeriod.Months,
anchor_fit_dataset = True )
tsExecuteEngine.evaluate()
tsExecuteEngine.getSummaryMetrics().to_excel("WFA-Backtest-2 backtest-metrics.xlsx")
DOW Jones
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']].\
query('TA_Reg_Name.str.contains("DJI")', engine='python')
Nasdaq
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']].\
query('TA_Reg_Name.str.contains("IXIC")', engine='python')
S&P 500
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']].\
query('TA_Reg_Name.str.contains("GSPC")', engine='python')
Dow Jones
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'trade_asset', 'order_type',
'enter_num_models', 'enter_model', 'enter_model_type',
'exit_num_models', 'exit_model', 'exit_model_type',
'stop_model', 'stop_model_type',
'Start Period', 'End Period',
'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ].\
query('trade_asset == "^DJI" ')
Nasdaq
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'trade_asset', 'order_type',
'enter_num_models', 'enter_model', 'enter_model_type',
'exit_num_models', 'exit_model', 'exit_model_type',
'stop_model', 'stop_model_type',
'Start Period', 'End Period',
'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ].\
query('trade_asset == "^IXIC" ')
S&P 500
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'trade_asset', 'order_type',
'enter_num_models', 'enter_model', 'enter_model_type',
'exit_num_models', 'exit_model', 'exit_model_type',
'stop_model', 'stop_model_type',
'Start Period', 'End Period',
'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ].\
query('trade_asset == "^GSPC" ')
Description:
Backtest:
1. Type: WFA Backtest
2. AI Models Fit Date Ranges
1. Training Period:
1. Begin Date = 2003-01-01
2. End Date = 2008-12-31
2. Validation Period:
1. Begin Date = 2009-01-01
2. End Date = 2010-12-31
4. Test Period:
1. Begin Date = 2011-01-01
2. End Date = 2012-12-31
portfolio_trade_assets = [ "^DJI", "^IXIC", "^GSPC" ]
dirPathMarketData = '../Data/US_Market_Indixes'
supportedTradeAssets = [ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
beg_date_str = "1980-01-01"
end_date_str = None
ts_marketdat_mng = TradeStrategyMarketDataMng(\
marketDataProviderName = "yahoofinance",
supportedTradeAssets = supportedTradeAssets,
stock_price_col_name = "Adj Close",
fileNameMarketData = "US_Indixes_And_ETFs_MrkData_From_1980",
dirPathMarketData = dirPathMarketData,
beg_date_str = beg_date_str,
end_date_str = end_date_str,
forceCreateMarketData = False,
interval = "1d" )
brokerTradingObj = SimBrokerTrading()
tsConfDat = TradeStrategyConfigData()
# Set Config
tsConfDat.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "entry" : { 'votingPolicy' : 1, 'incNoInvestInVotingDec' : False,
'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
'lastn_match' : 1, 'cross_over_signal_for_trading' : False },
"exit" : { 'votingPolicy' : 1,
'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
'lastn_match' : 1 }
}
} )
# TS #1
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_gru_1",
'actions_conf' : { "entry_exit" :
{ 'model' : "gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
"stop_lost" :
{ 'model' : "fix_perc",
'type' : "ta",
'obj_args' : { 'long_stop_los_per' : 5, 'short_stop_los_per' : 5 } }
},
} )
# TS #2
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_lstm",
'actions_conf' : { "entry_exit" :
{ 'model' : "lstm",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #3
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_conv1d_gru",
'actions_conf' : { "entry_exit" :
{ 'model' : "conv1d_gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #4
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_conv1d_lstm",
'actions_conf' : { "entry_exit" :
{ 'model' : "conv1d_lstm",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #5
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_wavenet",
'actions_conf' : { "entry_exit" :
{ 'model' : "wavenet",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #6
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_wavenet_gru",
'actions_conf' : { "entry_exit" :
{ 'model' : "wavenet_gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #7
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_wavenet_lstm",
'actions_conf' : { "entry_exit" :
{ 'model' : "wavenet_lstm",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #8
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_gru_2",
'actions_conf' : { "entry_exit" :
{ 'model' : "gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 40, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 3,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #9
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_1",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 10, 'win_slow' : 50 } ,
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #10
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_2",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 15, 'win_slow' : 60 } ,
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #11
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_bb",
'actions_conf' : { "entry_exit" :
{ 'model' : "bb",
'type' : "ta",
'obj_args' : { 'window' : 13, 'window_dev' : 1 } ,
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #12
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_macd",
'actions_conf' : { "entry_exit" :
{ 'model' : "macd",
'type' : "ta",
'obj_args' : { 'window_slow' : 26, 'window_fast' : 12, 'window_sign' : 9,
'enter_long_macd_diff' : 0.5 , 'exi_long_macd_diff' : 0.5,
'enter_short_macd_diff' : -0.5, 'exi_short_macd_diff' : -0.5 },
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #13
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_rsi",
'actions_conf' : { "entry_exit" :
{ 'model' : "rsi",
'type' : "ta",
'obj_args' : { 'rsi_enter_long' : 30.0, 'rsi_exit_long' : 30.0,
'rsi_enter_short' : 70.0, 'rsi_exit_short' : 70.0 },
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #14
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_srsi",
'actions_conf' : { "entry_exit" :
{ 'model' : "srsi",
'type' : "ta",
'obj_args' : { 'window' : 14, 'smooth1' : 3, 'smooth2' : 3,
'srsi_enter_long' : 0.8, 'srsi_exit_long' : 0.8,
'srsi_enter_short' : 0.2, 'srsi_exit_short' : 0.2 },
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #15
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_adx",
'actions_conf' : { "entry_exit" :
{ 'model' : "adx",
'type' : "ta",
'obj_args' : { 'window' : 14, 'adx_enter_long_ge' : 14, 'adx_exit_long_lt' : 14,
'adx_enter_short_ge' : 14, 'adx_exit_short_lt' : 14 },
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #16
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_kama",
'actions_conf' : { "entry_exit" :
{ 'model' : "kama",
'type' : "ta",
'obj_args' : { 'window_fast' : 10, 'pow1_fast' : 2, 'pow2_fast' : 30,
'window_slow' : 10, 'pow1_slow' : 5, 'pow2_slow' : 30 },
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #17
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_tsi",
'actions_conf' : { "entry_exit" :
{ 'model' : "tsi",
'type' : "ta",
'obj_args' : { 'window_slow' : 25, 'window_fast' : 5 },
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #18
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_forceindex",
'actions_conf' : { "entry_exit" :
{ 'model' : "forceindex",
'type' : "ta",
'obj_args' : { 'window' : 39 },
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #19
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_mfi",
'actions_conf' : { "entry_exit" :
{ 'model' : "mfi",
'type' : "ta",
'obj_args' : { 'window' : 14, 'long_slope_win' : 15, 'short_slope_win' : 15 },
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
taRegItemGen = TradeAssetRegisterItemGenerator()
portf_registered_obj = taRegItemGen.createTARegItem(
name_ta_reg_item = "WFA-Backtest 3",
# *** Trade Assets & Market Data
portfolio_trade_assets = portfolio_trade_assets,
ts_marketdat_mng = ts_marketdat_mng,
dirPathMarketData = dirPathMarketData,
market_data_period = MarketDataPeriod.Day,
# *** Broker
brokerTradingObj = brokerTradingObj,
# *** T.S. Permutations for each of the following sets of models
enter_exit_config_models = tsConfDat,
# *** Investment Manager Params
minPeriodsBetweenTrades = 1,
initInvestmentPerTradeStrategy = 2000000.0,
capPercentToInvestPerTrade = 100.0,
minInvestPercent = 5.0,
enter_trade_next_open_period = True,
min_account_balance = 1000.0,
portfRebalanceFreq = PortfolioRebalanceFrequency.Never,
portfRebalancePeriods = 1
)
print("Number of configured Trade Strategies: ", len(portf_registered_obj.taRegisterItems) )
training_period = DatasetDef(datasetType = DatasetType.Training,
strBegDateAIModels = "2002-07-01",
strBegDate = "2003-01-01",
strEndDate = "2008-12-31" )
validation_period = DatasetDef(datasetType = DatasetType.Validation,
strBegDateAIModels = "2008-07-01",
strBegDate = "2009-01-01",
strEndDate = "2010-12-31" )
testing_period = DatasetDef(datasetType = DatasetType.Testing,
strBegDateAIModels = "2010-07-01",
strBegDate = "2011-01-01",
strEndDate = "2012-12-31" )
fit_datasets = FitDatasetsDef( trainingDataset = training_period,
validationDataset = validation_period )
tsExecuteEngine = BacktestExecutionWFA( \
name = "WFA-Backtest 3",
test_period = testing_period,
fit_datasets_start = fit_datasets,
trade_asset_registered_item = portf_registered_obj,
wfa_slide_win_size = 6,
wfa_slide_win_period = WFASlideWindowPeriod.Months,
anchor_fit_dataset = False )
tsExecuteEngine.evaluate()
tsExecuteEngine.getSummaryMetrics().to_excel("WFA-Backtest-3 backtest-metrics.xlsx")
DOW Jones
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']].\
query('TA_Reg_Name.str.contains("DJI")', engine='python')
Nasdaq
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']].\
query('TA_Reg_Name.str.contains("IXIC")', engine='python')
S&P 500
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']].\
query('TA_Reg_Name.str.contains("GSPC")', engine='python')
Dow Jones
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'trade_asset', 'order_type',
'enter_num_models', 'enter_model', 'enter_model_type',
'exit_num_models', 'exit_model', 'exit_model_type',
'stop_model', 'stop_model_type',
'Start Period', 'End Period',
'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ].\
query('trade_asset == "^DJI" ')
Nasdaq
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'trade_asset', 'order_type',
'enter_num_models', 'enter_model', 'enter_model_type',
'exit_num_models', 'exit_model', 'exit_model_type',
'stop_model', 'stop_model_type',
'Start Period', 'End Period',
'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ].\
query('trade_asset == "^IXIC" ')
S&P 500
tsExecuteEngine.getSummaryMetrics()\
[ ['ta_reg_item_name', 'is_portfolio', 'trade_asset', 'order_type',
'enter_num_models', 'enter_model', 'enter_model_type',
'exit_num_models', 'exit_model', 'exit_model_type',
'stop_model', 'stop_model_type',
'Start Period', 'End Period',
'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ].\
query('trade_asset == "^GSPC" ')
session.add( tsExecuteEngine )
try :
session.commit()
except Exception as inst:
print(type(inst)) # the exception instance
print(inst)
print(inst.args) # arguments stored in .args
session.rollback() # roll back changes
finally:
print(" done")
- Description :
- Run a set of backtests by shifting the Training, Validation and Test Periods through time, or
increasing the duration of the Training and Validation Periods through time and shifting only
the Test Period
- Purpose of these set of backtest is to analysis the out-of-sample performance for trade strategies
and/or portfolios through time
- The sliding-window of the training, validation, and test periods are configurable.
- This type of backtest is combined with the regular WFA backtest, which allows to re-fit
models during each sliding window shift per the configuration of the regular WFA Backtest.
- This type of backtest can be thought of as double sliding window, one sliding window for shifting or
increasing the size of the training and validation periods, the second one to control how often
to re-fit models during a backtest.
- Due to the potential large number of backtests that can be executed, only the metadata, and summary
statistics and performance data are stored per backtest.
- All backtest statistical and metadata summary information is stored in a dataframe
- The metadata information stored includes actual Fit Data Ranges, Test Period, and re-fit
frequency during a backtest
- Example A:
- Scenario 1:
- Fix Fit and Test Periods.
- Given the following initial setting for a backtest:
Fit Dataset:
train: 1/1/2000 to 12/31/2004
validation: 1/1/2005 to 12/31/2005
Test Period: 1/1/2006 to 12/31/2006
- Run WFA backtests with the datasets above for different re-fit set frequencies, non-anchored:
- 2 weeks
- 1 month
- 3 month
- This example will run the WFA defined part 1, three-times, re-fitting the AI models each time
per the frequency defined.
- Example B:
- Scenario 2:
- WFA Scenario implementation that slides through time the Fit datasets as well as the test period.
- Given the following initial setting for a backtest:
Fit Dataset:
train: 1/1/2000 to 12/31/2004
validation: 1/1/2005 to 12/31/2005
Test Period: 1/1/2006 to 12/31/2006
- Run WFA backtests from the starting datasets above, incrementing sliding window of the datasets
for the Fit and Test periods by one-year, while the end date for the test period is less than
or equal to 12/31/2020
- Re-fit the AI Models in a backtest every 6 months, don't anchor the training set
- Each Iteration is one complete backtest, and in each backtest the AI Models are fitted at
the start and at July 1 of the current backtest year.
Iteration 1:
train: 1/1/2000 to 12/31/2004
validation: 1/1/2005 to 12/31/2005
Test Period: 1/1/2006 to 12/31/2006
Iteration 2:
train: 1/1/2001 to 12/31/2005
validation: 1/1/2006 to 12/31/2006
Test Period: 1/1/2007 to 12/31/2007
..
..
Iteration Last:
train: 1/1/2014 to 12/31/2018
validation: 1/1/2019 to 12/31/2019
Test Period: 1/1/2020 to 12/31/2020
- Example C:
- Scenario 3:
- WFA Scenario implementation that increases through time the date range of the Fit datasets,
but not the test period, as the fit dataset is anchored to its initial position.
- The train set is anchored, and the train and validation set are expanded in every iteration,
pushing the test period dataset forward in time, but with the same length.
- The increased per iteration of the train and validation set are configurable, as well as
the maximum end date for the test period.
- Given the following initial setting for a backtest:
Fit Dataset:
train: 1/1/2000 to 12/31/2004
validation: 1/1/2005 to 12/31/2005
Test Period: 1/1/2006 to 12/31/2006
- Run WFA backtests from the starting datasets above, incrementing sliding window of the datasets
for the Fit and Test periods by one-year, while the end date for the test period is less than
or equal to 12/31/2020
- Re-fit the AI Models in a backtest every 6 months, don't anchor the training set
- This class will iterate through time by creating updated Fit datsets, and Test Periods, with
one year increments overall to the train and validation period. Train dataset increased by 9 months
per iteration, and Validation dataset by 3 months, the test period is just shifted by the one-year.
- that is:
* Iteration 1:
train: 1/1/2000 to 12/31/2004
validation: 1/1/2005 to 12/31/2005
Test Period: 1/1/2006 to 12/31/2006
* Iteration 2:
train: 1/1/2000 to 9/30/2005 (date range increased by nine-months)
validation: 10/1/2005 to 12/31/2006 (date range increaed by three-months and
shifted by nine-months)
Test Period: 1/1/2007 to 12/31/2007 (date range shifted by one-year)
* Iteration 3:
train: 1/1/2000 to 6/30/2006 (date range increased by nine-months)
validation: 7/1/2006 to 12/31/2007 (date range increaed by three-months and
shifted by nine-months)
Test Period: 1/1/2008 to 12/31/2008 (date range shifted by one-year)
..
..
* Iteration Last:
train: 1/1/2000 to xxx
validation: yyy to 12/31/2019
Test Period: 1/1/2020 to 12/31/2020
Description:
Backtest:
1. Type: Slide Window WFA Backtest
2. AI Models Fit Date Ranges
1. Training Period:
1. Begin Date = 2000-01-01
2. End Date = 2005-12-31
2. Validation Period:
1. Begin Date = 2006-01-01
2. End Date = 2007-12-31
3. Test Period:
1. Begin Date = 2008-01-01
2. End Date = 2008-12-31
portfolio_trade_assets = [ "^DJI", "^IXIC", "^GSPC" ]
dirPathMarketData = '../Data/US_Market_Indixes'
supportedTradeAssets = [ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
beg_date_str = "1980-01-01"
end_date_str = None
ts_marketdat_mng = TradeStrategyMarketDataMng(\
marketDataProviderName = "yahoofinance",
supportedTradeAssets = supportedTradeAssets,
stock_price_col_name = "Adj Close",
fileNameMarketData = "US_Indixes_And_ETFs_MrkData_From_1980",
dirPathMarketData = dirPathMarketData,
beg_date_str = beg_date_str,
end_date_str = end_date_str,
forceCreateMarketData = False,
interval = "1d" )
MarketData.getDateRangesForStocks( ts_marketdat_mng.marketDataObj.getDataFrame() )
brokerTradingObj = SimBrokerTrading()
tsConfDat = TradeStrategyConfigData()
# Set Config
tsConfDat.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "entry" : { 'votingPolicy' : 1, 'incNoInvestInVotingDec' : False,
'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
'lastn_match' : 1, 'cross_over_signal_for_trading' : False },
"exit" : { 'votingPolicy' : 1,
'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
'lastn_match' : 1 }
}
} )
# TS #1
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_gru_1",
'actions_conf' : { "entry_exit" :
{ 'model' : "gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #2
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_lstm",
'actions_conf' : { "entry_exit" :
{ 'model' : "lstm",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #3
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_conv1d_gru",
'actions_conf' : { "entry_exit" :
{ 'model' : "conv1d_gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #4
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_conv1d_lstm",
'actions_conf' : { "entry_exit" :
{ 'model' : "conv1d_lstm",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #5
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_wavenet",
'actions_conf' : { "entry_exit" :
{ 'model' : "wavenet",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #6
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_wavenet_gru",
'actions_conf' : { "entry_exit" :
{ 'model' : "wavenet_gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #7
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_wavenet_lstm",
'actions_conf' : { "entry_exit" :
{ 'model' : "wavenet_lstm",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #8
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_gru_2",
'actions_conf' : { "entry_exit" :
{ 'model' : "gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 40, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 3,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
taRegItemGen = TradeAssetRegisterItemGenerator()
portf_registered_obj = taRegItemGen.createTARegItem(
name_ta_reg_item = "SW-WFA-Backtest 1",
# *** Trade Assets & Market Data
portfolio_trade_assets = portfolio_trade_assets,
ts_marketdat_mng = ts_marketdat_mng,
dirPathMarketData = dirPathMarketData,
market_data_period = MarketDataPeriod.Day,
# *** Broker
brokerTradingObj = brokerTradingObj,
# *** T.S. Permutations for each of the following sets of models
enter_exit_config_models = tsConfDat,
# *** Investment Manager Params
minPeriodsBetweenTrades = 1,
initInvestmentPerTradeStrategy = 2000000.0,
capPercentToInvestPerTrade = 100.0,
minInvestPercent = 5.0,
enter_trade_next_open_period = True,
min_account_balance = 1000.0,
portfRebalanceFreq = PortfolioRebalanceFrequency.Never,
portfRebalancePeriods = 1
)
print("Number of configured Trade Strategies: ", len(portf_registered_obj.taRegisterItems) )
training_period = DatasetDef(datasetType = DatasetType.Training,
strBegDateAIModels = "1999-07-01",
strBegDate = "2000-01-01",
strEndDate = "2005-12-31" )
validation_period = DatasetDef(datasetType = DatasetType.Validation,
strBegDateAIModels = "2005-07-01",
strBegDate = "2006-01-01",
strEndDate = "2007-12-31" )
testing_period = DatasetDef(datasetType = DatasetType.Testing,
strBegDateAIModels = "2007-07-01",
strBegDate = "2008-01-01",
strEndDate = "2008-12-31" )
fit_datasets = FitDatasetsDef( trainingDataset = training_period,
validationDataset = validation_period )
tsExecuteEngine = BacktestExecutionSlideWindowWFA( \
name = "SW-WFA-Backtest 1",
trade_asset_registered_item = portf_registered_obj,
wfa_slide_win_size_list = [ 3, 6] , # list of int, associated with wfa_slide_win_period_list
wfa_slide_win_period_list = [ WFASlideWindowPeriod.Months, WFASlideWindowPeriod.Months ],
wfa_sw_scenario_obj = WFASlideWinScenarioFixDatasets(fit_dataset = fit_datasets,
test_period = testing_period ),
anchor_fit_dataset = False )
tsExecuteEngine.evaluate()
tsExecuteEngine.getSummaryMetrics().to_excel("SW-WFA-Backtest-1 backtest-metrics.xlsx")
tsExecuteEngine.getSummaryMetrics().info()
tsExecuteEngine.getSummaryMetrics()\
[ [ 'wfa_sw_iter_no', 'wfa_slide_win_size', 'wfa_slide_win_period',
'ta_reg_item_name', 'is_portfolio', 'trade_asset', 'order_type',
'enter_num_models', 'enter_model', 'enter_model_type',
'exit_num_models', 'exit_model', 'exit_model_type',
'stop_model', 'stop_model_type',
'Start Period', 'End Period',
'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ].\
query('trade_asset == "^DJI" ')
tsExecuteEngine.getSummaryMetrics()\
[ [ 'wfa_sw_iter_no', 'wfa_slide_win_size', 'wfa_slide_win_period',
'ta_reg_item_name', 'is_portfolio', 'trade_asset', 'order_type',
'enter_num_models', 'enter_model', 'enter_model_type',
'exit_num_models', 'exit_model', 'exit_model_type',
'stop_model', 'stop_model_type',
'Start Period', 'End Period',
'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ].\
query('trade_asset == "^IXIC" ')
tsExecuteEngine.getSummaryMetrics()\
[ [ 'wfa_sw_iter_no', 'wfa_slide_win_size', 'wfa_slide_win_period',
'ta_reg_item_name', 'is_portfolio', 'trade_asset', 'order_type',
'enter_num_models', 'enter_model', 'enter_model_type',
'exit_num_models', 'exit_model', 'exit_model_type',
'stop_model', 'stop_model_type',
'Start Period', 'End Period',
'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ].\
query('trade_asset == "^GSPC" ')
session.add( tsExecuteEngine )
try :
session.commit()
except Exception as inst:
print(type(inst)) # the exception instance
print(inst)
print(inst.args) # arguments stored in .args
session.rollback() # roll back changes
finally:
print(" done")
Description:
Backtest:
1. Type: Slide Window WFA Backtest
2. Start AI Models Fit Date Ranges
1. Training Period:
1. Begin Date = 2000-01-01
2. End Date = 2005-12-31
2. Validation Period:
1. Begin Date = 2006-01-01
2. End Date = 2007-12-31
3. Final AI Models Fit Date Ranges
1. Training Period:
1. Begin Date = 2004-01-01
2. End Date = 2009-12-31
2. Validation Period:
1. Begin Date = 2010-01-01
2. End Date = 2011-12-31
4. Start Test Period:
1. Begin Date = 2008-01-01
2. End Date = 2008-12-31
5. Final Test Period:
1. Begin Date = 2012-01-01
2. End Date = 2012-12-31
portfolio_trade_assets = [ "^DJI", "^IXIC", "^GSPC" ]
dirPathMarketData = '../Data/US_Market_Indixes'
supportedTradeAssets = [ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
beg_date_str = "1980-01-01"
end_date_str = None
ts_marketdat_mng = TradeStrategyMarketDataMng(\
marketDataProviderName = "yahoofinance",
supportedTradeAssets = supportedTradeAssets,
stock_price_col_name = "Adj Close",
fileNameMarketData = "US_Indixes_And_ETFs_MrkData_From_1980",
dirPathMarketData = dirPathMarketData,
beg_date_str = beg_date_str,
end_date_str = end_date_str,
forceCreateMarketData = False,
interval = "1d" )
brokerTradingObj = SimBrokerTrading()
tsConfDat = TradeStrategyConfigData()
# Set Config
tsConfDat.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "entry" : { 'votingPolicy' : 1, 'incNoInvestInVotingDec' : False,
'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
'lastn_match' : 1, 'cross_over_signal_for_trading' : False },
"exit" : { 'votingPolicy' : 1,
'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
'lastn_match' : 1 }
}
} )
# TS #1
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_gru_1",
'actions_conf' : { "entry_exit" :
{ 'model' : "gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #2
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_lstm",
'actions_conf' : { "entry_exit" :
{ 'model' : "lstm",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #3
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_conv1d_gru",
'actions_conf' : { "entry_exit" :
{ 'model' : "conv1d_gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #4
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_conv1d_lstm",
'actions_conf' : { "entry_exit" :
{ 'model' : "conv1d_lstm",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #5
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_wavenet",
'actions_conf' : { "entry_exit" :
{ 'model' : "wavenet",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #6
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_wavenet_gru",
'actions_conf' : { "entry_exit" :
{ 'model' : "wavenet_gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #7
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_wavenet_lstm",
'actions_conf' : { "entry_exit" :
{ 'model' : "wavenet_lstm",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #8
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_gru_2",
'actions_conf' : { "entry_exit" :
{ 'model' : "gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 40, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 3,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
taRegItemGen = TradeAssetRegisterItemGenerator()
portf_registered_obj = taRegItemGen.createTARegItem(
name_ta_reg_item = "SW-WFA-Backtest 2",
# *** Trade Assets & Market Data
portfolio_trade_assets = portfolio_trade_assets,
ts_marketdat_mng = ts_marketdat_mng,
dirPathMarketData = dirPathMarketData,
market_data_period = MarketDataPeriod.Day,
# *** Broker
brokerTradingObj = brokerTradingObj,
# *** T.S. Permutations for each of the following sets of models
enter_exit_config_models = tsConfDat,
# *** Investment Manager Params
minPeriodsBetweenTrades = 1,
initInvestmentPerTradeStrategy = 2000000.0,
capPercentToInvestPerTrade = 100.0,
minInvestPercent = 5.0,
enter_trade_next_open_period = True,
min_account_balance = 1000.0,
portfRebalanceFreq = PortfolioRebalanceFrequency.Never,
portfRebalancePeriods = 1
)
print("Number of configured Trade Strategies: ", len(portf_registered_obj.taRegisterItems) )
training_period = DatasetDef(datasetType = DatasetType.Training,
strBegDateAIModels = "1999-07-01",
strBegDate = "2000-01-01",
strEndDate = "2005-12-31" )
validation_period = DatasetDef(datasetType = DatasetType.Validation,
strBegDateAIModels = "2005-07-01",
strBegDate = "2006-01-01",
strEndDate = "2007-12-31" )
testing_period = DatasetDef(datasetType = DatasetType.Testing,
strBegDateAIModels = "2007-07-01",
strBegDate = "2008-01-01",
strEndDate = "2008-12-31" )
fit_datasets = FitDatasetsDef( trainingDataset = training_period,
validationDataset = validation_period )
tsExecuteEngine = BacktestExecutionSlideWindowWFA( \
name = "SW-WFA-Backtest 2",
trade_asset_registered_item = portf_registered_obj,
wfa_slide_win_size_list = [ 3 ] , # list of int, associated with wfa_slide_win_period_list
wfa_slide_win_period_list = [ WFASlideWindowPeriod.Months ],
wfa_sw_scenario_obj = WFASlideWinScenarioSlidingDatasets(\
fit_dataset = fit_datasets,
test_period = testing_period,
slide_win_size = 1,
slide_win_period = WFASlideWindowPeriod.Years,
end_date_last_test_period = datetime(year=2012, month=12, day=31) ),
anchor_fit_dataset = False )
tsExecuteEngine.evaluate()
tsExecuteEngine.getSummaryMetrics().to_excel("SW-WFA-Backtest-2 backtest-metrics.xlsx")
tsExecuteEngine.getSummaryMetrics()\
[ [ 'wfa_sw_iter_no', 'wfa_slide_win_size', 'wfa_slide_win_period',
'ta_reg_item_name', 'is_portfolio', 'trade_asset', 'order_type',
'enter_num_models', 'enter_model', 'enter_model_type',
'exit_num_models', 'exit_model', 'exit_model_type',
'stop_model', 'stop_model_type',
'Start Period', 'End Period',
'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ].\
query('trade_asset == "^DJI" ')
tsExecuteEngine.getSummaryMetrics()\
[ [ 'wfa_sw_iter_no', 'wfa_slide_win_size', 'wfa_slide_win_period',
'ta_reg_item_name', 'is_portfolio', 'trade_asset', 'order_type',
'enter_num_models', 'enter_model', 'enter_model_type',
'exit_num_models', 'exit_model', 'exit_model_type',
'stop_model', 'stop_model_type',
'Start Period', 'End Period',
'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ].\
query('trade_asset == "^IXIC" ')
tsExecuteEngine.getSummaryMetrics()\
[ [ 'wfa_sw_iter_no', 'wfa_slide_win_size', 'wfa_slide_win_period',
'ta_reg_item_name', 'is_portfolio', 'trade_asset', 'order_type',
'enter_num_models', 'enter_model', 'enter_model_type',
'exit_num_models', 'exit_model', 'exit_model_type',
'stop_model', 'stop_model_type',
'Start Period', 'End Period',
'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ].\
query('trade_asset == "^GSPC" ')
Description:
Backtest:
Type: Slide Window WFA Backtest
Iteration 1:
train: 1/1/1995 to 12/31/2000
validation: 1/1/2001 to 12/31/2002
Test Period: 1/1/2003 to 12/31/2003
Iteration 2:
train: 1/1/1995 to 9/30/2001 (date range increased by nine-months)
validation: 10/1/2001 to 12/31/2003 (date range increased by three-months and shifted
by nine-months)
Test Period: 1/1/2004 to 12/31/2004 (date range shifted by one-year)
Iteration 3:
train: 1/1/1995 to 6/30/2002 (date range increased by nine-months)
validation: 7/1/2002 to 12/31/2004 (date range increaed by three-months and shifted
by nine-months)
Test Period: 1/1/2005 to 12/31/2005 (date range shifted by one-year)
...
...
Iteration Last:
train: 1/1/2000 to xxx
validation: yyy to 12/31/2006
Test Period: 1/1/2007 to 12/31/2007
portfolio_trade_assets = [ "^DJI", "^IXIC", "^GSPC" ]
dirPathMarketData = '../Data/US_Market_Indixes'
supportedTradeAssets = [ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
beg_date_str = "1980-01-01"
end_date_str = None
ts_marketdat_mng = TradeStrategyMarketDataMng(\
marketDataProviderName = "yahoofinance",
supportedTradeAssets = supportedTradeAssets,
stock_price_col_name = "Adj Close",
fileNameMarketData = "US_Indixes_And_ETFs_MrkData_From_1980",
dirPathMarketData = dirPathMarketData,
beg_date_str = beg_date_str,
end_date_str = end_date_str,
forceCreateMarketData = False,
interval = "1d" )
brokerTradingObj = SimBrokerTrading()
tsConfDat = TradeStrategyConfigData()
# Set Config
tsConfDat.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "entry" : { 'votingPolicy' : 1, 'incNoInvestInVotingDec' : False,
'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
'lastn_match' : 1, 'cross_over_signal_for_trading' : False },
"exit" : { 'votingPolicy' : 1,
'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
'lastn_match' : 1 }
}
} )
# TS #1
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_gru_1",
'actions_conf' : { "entry_exit" :
{ 'model' : "gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
"stop_lost" :
{ 'model' : "fix_perc",
'type' : "ta",
'obj_args' : { 'long_stop_los_per' : 5, 'short_stop_los_per' : 5 } }
},
} )
# TS #2
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_lstm",
'actions_conf' : { "entry_exit" :
{ 'model' : "lstm",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #3
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_conv1d_gru",
'actions_conf' : { "entry_exit" :
{ 'model' : "conv1d_gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #4
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_conv1d_lstm",
'actions_conf' : { "entry_exit" :
{ 'model' : "conv1d_lstm",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #5
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_wavenet",
'actions_conf' : { "entry_exit" :
{ 'model' : "wavenet",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #6
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_wavenet_gru",
'actions_conf' : { "entry_exit" :
{ 'model' : "wavenet_gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #7
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_wavenet_lstm",
'actions_conf' : { "entry_exit" :
{ 'model' : "wavenet_lstm",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #8
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_gru_2",
'actions_conf' : { "entry_exit" :
{ 'model' : "gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 40, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 3,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #9
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_1",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 10, 'win_slow' : 50 } ,
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #10
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_2",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 15, 'win_slow' : 60 } ,
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #11
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_bb",
'actions_conf' : { "entry_exit" :
{ 'model' : "bb",
'type' : "ta",
'obj_args' : { 'window' : 13, 'window_dev' : 1 } ,
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #12
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_macd",
'actions_conf' : { "entry_exit" :
{ 'model' : "macd",
'type' : "ta",
'obj_args' : { 'window_slow' : 26, 'window_fast' : 12, 'window_sign' : 9,
'enter_long_macd_diff' : 0.5 , 'exi_long_macd_diff' : 0.5,
'enter_short_macd_diff' : -0.5, 'exi_short_macd_diff' : -0.5 },
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #13
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_rsi",
'actions_conf' : { "entry_exit" :
{ 'model' : "rsi",
'type' : "ta",
'obj_args' : { 'rsi_enter_long' : 30.0, 'rsi_exit_long' : 30.0,
'rsi_enter_short' : 70.0, 'rsi_exit_short' : 70.0 },
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #14
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_srsi",
'actions_conf' : { "entry_exit" :
{ 'model' : "srsi",
'type' : "ta",
'obj_args' : { 'window' : 14, 'smooth1' : 3, 'smooth2' : 3,
'srsi_enter_long' : 0.8, 'srsi_exit_long' : 0.8,
'srsi_enter_short' : 0.2, 'srsi_exit_short' : 0.2 },
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #15
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_adx",
'actions_conf' : { "entry_exit" :
{ 'model' : "adx",
'type' : "ta",
'obj_args' : { 'window' : 14, 'adx_enter_long_ge' : 14, 'adx_exit_long_lt' : 14,
'adx_enter_short_ge' : 14, 'adx_exit_short_lt' : 14 },
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #16
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_kama",
'actions_conf' : { "entry_exit" :
{ 'model' : "kama",
'type' : "ta",
'obj_args' : { 'window_fast' : 10, 'pow1_fast' : 2, 'pow2_fast' : 30,
'window_slow' : 10, 'pow1_slow' : 5, 'pow2_slow' : 30 },
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #17
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_tsi",
'actions_conf' : { "entry_exit" :
{ 'model' : "tsi",
'type' : "ta",
'obj_args' : { 'window_slow' : 25, 'window_fast' : 5 },
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #18
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_forceindex",
'actions_conf' : { "entry_exit" :
{ 'model' : "forceindex",
'type' : "ta",
'obj_args' : { 'window' : 39 },
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #19
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_mfi",
'actions_conf' : { "entry_exit" :
{ 'model' : "mfi",
'type' : "ta",
'obj_args' : { 'window' : 14, 'long_slope_win' : 15, 'short_slope_win' : 15 },
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
taRegItemGen = TradeAssetRegisterItemGenerator()
portf_registered_obj = taRegItemGen.createTARegItem(
name_ta_reg_item = "SW-WFA-Backtest 3",
# *** Trade Assets & Market Data
portfolio_trade_assets = portfolio_trade_assets,
ts_marketdat_mng = ts_marketdat_mng,
dirPathMarketData = dirPathMarketData,
market_data_period = MarketDataPeriod.Day,
# *** Broker
brokerTradingObj = brokerTradingObj,
# *** T.S. Permutations for each of the following sets of models
enter_exit_config_models = tsConfDat,
# *** Investment Manager Params
minPeriodsBetweenTrades = 1,
initInvestmentPerTradeStrategy = 2000000.0,
capPercentToInvestPerTrade = 100.0,
minInvestPercent = 5.0,
enter_trade_next_open_period = True,
min_account_balance = 1000.0,
portfRebalanceFreq = PortfolioRebalanceFrequency.Never,
portfRebalancePeriods = 1
)
print("Number of configured Trade Strategies: ", len(portf_registered_obj.taRegisterItems) )
training_period = DatasetDef(datasetType = DatasetType.Training,
strBegDateAIModels = "1994-07-01",
strBegDate = "1995-01-01",
strEndDate = "2000-12-31" )
validation_period = DatasetDef(datasetType = DatasetType.Validation,
strBegDateAIModels = "2000-07-01",
strBegDate = "2001-01-01",
strEndDate = "2002-12-31" )
testing_period = DatasetDef(datasetType = DatasetType.Testing,
strBegDateAIModels = "2002-07-01",
strBegDate = "2003-01-01",
strEndDate = "2003-12-31" )
fit_datasets = FitDatasetsDef( trainingDataset = training_period,
validationDataset = validation_period )
tsExecuteEngine = BacktestExecutionSlideWindowWFA( \
name = "SW-WFA-Backtest 3",
trade_asset_registered_item = portf_registered_obj,
wfa_slide_win_size_list = [ 3 ] , # list of int, associated with wfa_slide_win_period_list
wfa_slide_win_period_list = [ WFASlideWindowPeriod.Months ],
wfa_sw_scenario_obj = WFASlideWinScenarioAnchoredSlidingDatasets(\
fit_dataset = fit_datasets,
test_period = testing_period,
train_slide_win_size = 9, # increase train set 9 months every sw incr
val_slide_win_size = 3, # increase val set 3 months every sw incr
# and shift by 9 months
slide_win_period = WFASlideWindowPeriod.Months,
end_date_last_test_period = datetime(year=2007, month=12, day=31) ),
anchor_fit_dataset = True )
tsExecuteEngine.evaluate()
tsExecuteEngine.getSummaryMetrics().to_excel("SW-WFA-Backtest-3 backtest-metrics.xlsx")
tsExecuteEngine.getSummaryMetrics()\
[ [ 'wfa_sw_iter_no', 'wfa_slide_win_size', 'wfa_slide_win_period',
'ta_reg_item_name', 'is_portfolio', 'trade_asset', 'order_type',
'enter_num_models', 'enter_model', 'enter_model_type',
'exit_num_models', 'exit_model', 'exit_model_type',
'stop_model', 'stop_model_type',
'Start Period', 'End Period',
'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ].\
query('trade_asset == "^DJI" ')
tsExecuteEngine.getSummaryMetrics()\
[ [ 'wfa_sw_iter_no', 'wfa_slide_win_size', 'wfa_slide_win_period',
'ta_reg_item_name', 'is_portfolio', 'trade_asset', 'order_type',
'enter_num_models', 'enter_model', 'enter_model_type',
'exit_num_models', 'exit_model', 'exit_model_type',
'stop_model', 'stop_model_type',
'Start Period', 'End Period',
'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ].\
query('trade_asset == "^IXIC" ')
tsExecuteEngine.getSummaryMetrics()\
[ [ 'wfa_sw_iter_no', 'wfa_slide_win_size', 'wfa_slide_win_period',
'ta_reg_item_name', 'is_portfolio', 'trade_asset', 'order_type',
'enter_num_models', 'enter_model', 'enter_model_type',
'exit_num_models', 'exit_model', 'exit_model_type',
'stop_model', 'stop_model_type',
'Start Period', 'End Period',
'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ].\
query('trade_asset == "^GSPC" ')
Description:
Backtest:
Type: Slide Window WFA Backtest
Iteration 1:
train: 1/1/1994 to 12/31/1998
validation: 1/1/1999 to 12/31/2000
Test Period: 1/1/2001 to 12/31/2001
...
...
Iteration Last:
train: 1/1/2003 to 12/31/2007
validation: 1/1/2008 to 12/31/2009
Test Period: 1/1/2010 to 12/31/2010
portfolio_trade_assets = [ "^DJI", "^IXIC", "^GSPC" ]
dirPathMarketData = '../Data/US_Market_Indixes'
supportedTradeAssets = [ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
beg_date_str = "1980-01-01"
end_date_str = None
ts_marketdat_mng = TradeStrategyMarketDataMng(\
marketDataProviderName = "yahoofinance",
supportedTradeAssets = supportedTradeAssets,
stock_price_col_name = "Adj Close",
fileNameMarketData = "US_Indixes_And_ETFs_MrkData_From_1980",
dirPathMarketData = dirPathMarketData,
beg_date_str = beg_date_str,
end_date_str = end_date_str,
forceCreateMarketData = False,
interval = "1d" )
brokerTradingObj = SimBrokerTrading()
tsConfDat_SuperSet = TradeStrategyConfigData()
# Set Config
tsConfDat_SuperSet.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "entry" : { 'votingPolicy' : 1, 'incNoInvestInVotingDec' : False,
'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
'lastn_match' : 1, 'cross_over_signal_for_trading' : False },
"exit" : { 'votingPolicy' : 1,
'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
'lastn_match' : 1 }
}
} )
# TS #1
tsConfDat_SuperSet.addTSConf(\
ts_conf_dict = {
'set_categories' : [ "TA" ],
'ts_unique_tag' : "ts_macd_1",
'actions_conf' : { "entry_exit" :
{ 'model' : "macd",
'type' : "ta",
'obj_args' : { 'window_slow' : 18, 'window_fast' : 7, 'window_sign' : 9,
'enter_long_macd_diff' : 0.5 , 'exi_long_macd_diff' : 0.5,
'enter_short_macd_diff' : -0.5, 'exi_short_macd_diff' : -0.5 },
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #2
tsConfDat_SuperSet.addTSConf(\
ts_conf_dict = {
'set_categories' : [ "TA" ],
'ts_unique_tag' : "ts_bb_1",
'actions_conf' : { "entry_exit" :
{ 'model' : "bb",
'type' : "ta",
'obj_args' : { 'window' : 7, 'window_dev' : 1 } ,
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #3
tsConfDat_SuperSet.addTSConf(\
ts_conf_dict = {
'set_categories' : [ "TA" ],
'ts_unique_tag' : "ts_sma_1x",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 10, 'win_slow' : 50 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #4
tsConfDat_SuperSet.addTSConf(\
ts_conf_dict = {
'set_categories' : [ "TA" ],
'ts_unique_tag' : "ts_macd_2",
'actions_conf' : { "entry_exit" :
{ 'model' : "macd",
'type' : "ta",
'obj_args' : { 'window_slow' : 26, 'window_fast' : 12, 'window_sign' : 9,
'enter_long_macd_diff' : 0.5 , 'exi_long_macd_diff' : 0.5,
'enter_short_macd_diff' : -0.5, 'exi_short_macd_diff' : -0.5 },
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #5
tsConfDat_SuperSet.addTSConf(\
ts_conf_dict = {
'set_categories' : [ "TA" ],
'ts_unique_tag' : "ts_rsi",
'actions_conf' : { "entry_exit" :
{ 'model' : "rsi",
'type' : "ta",
'obj_args' : { 'rsi_enter_long' : 30.0, 'rsi_exit_long' : 30.0,
'rsi_enter_short' : 70.0, 'rsi_exit_short' : 70.0 },
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #6
tsConfDat_SuperSet.addTSConf(\
ts_conf_dict = {
'set_categories' : [ "TA" ],
'ts_unique_tag' : "ts_srsi",
'actions_conf' : { "entry_exit" :
{ 'model' : "srsi",
'type' : "ta",
'obj_args' : { 'window' : 14, 'smooth1' : 3, 'smooth2' : 3,
'srsi_enter_long' : 0.8, 'srsi_exit_long' : 0.8,
'srsi_enter_short' : 0.2, 'srsi_exit_short' : 0.2 },
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #7
tsConfDat_SuperSet.addTSConf(\
ts_conf_dict = {
'set_categories' : [ "TA" ],
'ts_unique_tag' : "ts_adx",
'actions_conf' : { "entry_exit" :
{ 'model' : "adx",
'type' : "ta",
'obj_args' : { 'window' : 14, 'adx_enter_long_ge' : 14, 'adx_exit_long_lt' : 14,
'adx_enter_short_ge' : 14, 'adx_exit_short_lt' : 14 },
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #8
tsConfDat_SuperSet.addTSConf(\
ts_conf_dict = {
'set_categories' : [ "TA" ],
'ts_unique_tag' : "ts_kama",
'actions_conf' : { "entry_exit" :
{ 'model' : "kama",
'type' : "ta",
'obj_args' : { 'window_fast' : 10, 'pow1_fast' : 2, 'pow2_fast' : 30,
'window_slow' : 10, 'pow1_slow' : 5, 'pow2_slow' : 30 },
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #9
tsConfDat_SuperSet.addTSConf(\
ts_conf_dict = {
'set_categories' : [ "TA" ],
'ts_unique_tag' : "ts_tsi",
'actions_conf' : { "entry_exit" :
{ 'model' : "tsi",
'type' : "ta",
'obj_args' : { 'window_slow' : 25, 'window_fast' : 5 },
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #10
tsConfDat_SuperSet.addTSConf(\
ts_conf_dict = {
'set_categories' : [ "TA" ],
'ts_unique_tag' : "ts_forceindex",
'actions_conf' : { "entry_exit" :
{ 'model' : "forceindex",
'type' : "ta",
'obj_args' : { 'window' : 39 },
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #11
tsConfDat_SuperSet.addTSConf(\
ts_conf_dict = {
'set_categories' : [ "TA" ],
'ts_unique_tag' : "ts_mfi",
'actions_conf' : { "entry_exit" :
{ 'model' : "mfi",
'type' : "ta",
'obj_args' : { 'window' : 14, 'long_slope_win' : 15, 'short_slope_win' : 15 },
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #12
tsConfDat_SuperSet.addTSConf(\
ts_conf_dict = {
'set_categories' : [ "AI" ],
'ts_unique_tag' : "ts_gru_1",
'actions_conf' : { "entry_exit" :
{ 'model' : "gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #13
tsConfDat_SuperSet.addTSConf(\
ts_conf_dict = {
'set_categories' : [ "AI" ],
'ts_unique_tag' : "ts_lstm",
'actions_conf' : { "entry_exit" :
{ 'model' : "lstm",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #14
tsConfDat_SuperSet.addTSConf(\
ts_conf_dict = {
'set_categories' : [ "AI" ],
'ts_unique_tag' : "ts_conv1d_gru",
'actions_conf' : { "entry_exit" :
{ 'model' : "conv1d_gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #15
tsConfDat_SuperSet.addTSConf(\
ts_conf_dict = {
'set_categories' : [ "AI" ],
'ts_unique_tag' : "ts_conv1d_lstm",
'actions_conf' : { "entry_exit" :
{ 'model' : "conv1d_lstm",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #16
tsConfDat_SuperSet.addTSConf(\
ts_conf_dict = {
'set_categories' : [ "AI" ],
'ts_unique_tag' : "ts_wavenet",
'actions_conf' : { "entry_exit" :
{ 'model' : "wavenet",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #17
tsConfDat_SuperSet.addTSConf(\
ts_conf_dict = {
'set_categories' : [ "AI" ],
'ts_unique_tag' : "ts_wavenet_gru",
'actions_conf' : { "entry_exit" :
{ 'model' : "wavenet_gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #18
tsConfDat_SuperSet.addTSConf(\
ts_conf_dict = {
'set_categories' : [ "AI" ],
'ts_unique_tag' : "ts_wavenet_lstm",
'actions_conf' : { "entry_exit" :
{ 'model' : "wavenet_lstm",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #19
tsConfDat_SuperSet.addTSConf(\
ts_conf_dict = {
'set_categories' : [ "AI" ],
'ts_unique_tag' : "ts_gru_2",
'actions_conf' : { "entry_exit" :
{ 'model' : "gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 40, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 3,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #20
tsConfDat_SuperSet.addTSConf(\
ts_conf_dict = {
'set_categories' : [ "SMA" ],
'ts_unique_tag' : "ts_sma_1",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 20, 'win_slow' : 100 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #21
tsConfDat_SuperSet.addTSConf(\
ts_conf_dict = {
'set_categories' : [ "SMA" ],
'ts_unique_tag' : "ts_sma_2",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 10, 'win_slow' : 50 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #22
tsConfDat_SuperSet.addTSConf(\
ts_conf_dict = {
'set_categories' : [ "SMA" ],
'ts_unique_tag' : "ts_sma_3",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 13, 'win_slow' : 65 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #23
tsConfDat_SuperSet.addTSConf(\
ts_conf_dict = {
'set_categories' : [ "SMA" ],
'ts_unique_tag' : "ts_sma_4",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 15, 'win_slow' : 60 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #24
tsConfDat_SuperSet.addTSConf(\
ts_conf_dict = {
'set_categories' : [ "SMA" ],
'ts_unique_tag' : "ts_sma_5",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 15, 'win_slow' : 75 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #25
tsConfDat_SuperSet.addTSConf(\
ts_conf_dict = {
'set_categories' : [ "SMA" ],
'ts_unique_tag' : "ts_sma_6",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 7, 'win_slow' : 35 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #26
tsConfDat_SuperSet.addTSConf(\
ts_conf_dict = {
'set_categories' : [ "SMA" ],
'ts_unique_tag' : "ts_sma_7",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 12, 'win_slow' : 40 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #27
tsConfDat_SuperSet.addTSConf(\
ts_conf_dict = {
'set_categories' : [ "SMA" ],
'ts_unique_tag' : "ts_sma_8",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 17, 'win_slow' : 80 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #28
tsConfDat_SuperSet.addTSConf(\
ts_conf_dict = {
'set_categories' : [ "SMA" ],
'ts_unique_tag' : "ts_sma_9",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 22, 'win_slow' : 90 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# ***
# *** Configure Several Types of Stop Actions
# ***
# order_type = 1 ( Stop-Loss )
# order_type = 2 ( Trail-Stop-Loss )
# order_type = 3 ( Combine Stop-Loss & Trail-Stop-Loss )
#
# Stop Models :
# fixval { user-defined stop-loss-percent and/or trail-stop-loss-percent }
# atr { uses ATR model to dynamically determined the stop and trail stop loss percents }
# *** Stop-Loss Order Type
tsStopsConfDat_Stop_Loss = TradeStrategyConfigData()
tsStopsConfDat_Stop_Loss.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "stop" : { 'order_type' : 1 } }
} )
# 1) *** Combine Stop-Loss & Trail-Stop-Loss Order Type - Using Fixed Values
tsStopsConfDat_Stop_Loss_And_Trail_SL_1 = TradeStrategyConfigData()
tsStopsConfDat_Stop_Loss_And_Trail_SL_1.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "stop" : { 'order_type' : 3 } }
} )
tsStopsConfDat_Stop_Loss_And_Trail_SL_1.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "sl_tsl_fixval",
'actions_conf' : { "stop" :
{ 'model' : "fixval",
'type' : "ta",
'obj_args' : { 'stop_loss_per' : 0.002, 'trail_stop_loss_per' : 0.005 },
},
},
} )
# 2) ***
tsStopsConfDat_Stop_Loss_And_Trail_SL_2 = TradeStrategyConfigData()
tsStopsConfDat_Stop_Loss_And_Trail_SL_2.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "stop" : { 'order_type' : 3 } }
} )
tsStopsConfDat_Stop_Loss_And_Trail_SL_2.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "sl_tsl_atr_2",
'actions_conf' : { "stop" :
{ 'model' : "atr",
'type' : "ta",
'obj_args' : { 'atr_mov_ave' : 7,
'stop_loss_mult' : 0.05,
'trail_stop_loss_mult' : 0.075,
},
},
},
} )
# 3) ***
tsStopsConfDat_Stop_Loss_And_Trail_SL_3 = TradeStrategyConfigData()
tsStopsConfDat_Stop_Loss_And_Trail_SL_3.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "stop" : { 'order_type' : 3 } }
} )
tsStopsConfDat_Stop_Loss_And_Trail_SL_3.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "sl_tsl_atr_3",
'actions_conf' : { "stop" :
{ 'model' : "atr",
'type' : "ta",
'obj_args' : { 'atr_mov_ave' : 7,
'stop_loss_mult' : 0.01,
'trail_stop_loss_mult' : 0.03,
},
},
},
} )
# *4) **
tsStopsConfDat_Stop_Loss_And_Trail_SL_4 = TradeStrategyConfigData()
tsStopsConfDat_Stop_Loss_And_Trail_SL_4.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "stop" : { 'order_type' : 3 } }
} )
tsStopsConfDat_Stop_Loss_And_Trail_SL_4.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "sl_tsl_atr_4",
'actions_conf' : { "stop" :
{ 'model' : "atr",
'type' : "ta",
'obj_args' : { 'atr_mov_ave' : 7,
'stop_loss_mult' : 0.0075,
'trail_stop_loss_mult' : 0.0095,
},
},
},
} )
# 5) ***
tsStopsConfDat_Stop_Loss_And_Trail_SL_5 = TradeStrategyConfigData()
tsStopsConfDat_Stop_Loss_And_Trail_SL_5.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "stop" : { 'order_type' : 3 } }
} )
tsStopsConfDat_Stop_Loss_And_Trail_SL_5.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "sl_tsl_atr_5",
'actions_conf' : { "stop" :
{ 'model' : "atr",
'type' : "ta",
'obj_args' : { 'atr_mov_ave' : 7,
'stop_loss_mult' : 0.0025,
'trail_stop_loss_mult' : 0.0050,
},
},
},
} )
stopsConfDatList = [ tsStopsConfDat_Stop_Loss_And_Trail_SL_1, tsStopsConfDat_Stop_Loss_And_Trail_SL_2,
tsStopsConfDat_Stop_Loss_And_Trail_SL_3, tsStopsConfDat_Stop_Loss_And_Trail_SL_4,
tsStopsConfDat_Stop_Loss_And_Trail_SL_5
]
taRegItemGen = TradeAssetRegisterItemGenerator()
portf_registered_obj = taRegItemGen.createTARegItem(
name_ta_reg_item = "SW-WFA-Backtest 4",
# *** Trade Assets & Market Data
portfolio_trade_assets = portfolio_trade_assets,
ts_marketdat_mng = ts_marketdat_mng,
dirPathMarketData = dirPathMarketData,
market_data_period = MarketDataPeriod.Day,
# *** Broker
brokerTradingObj = brokerTradingObj,
# *** T.S. Permutations for each of the following sets of models
enter_exit_config_models = tsConfDat_SuperSet,
stop_config_models = stopsConfDatList,
set_cats = [ "All", "TA", "AI", "SMA",
["TA", "AI"], ["TA", "SMA"], ["AI", "SMA"] ],
# *** Investment Manager Params
minPeriodsBetweenTrades = 1,
initInvestmentPerTradeStrategy = 2000000.0,
capPercentToInvestPerTrade = 100.0,
minInvestPercent = 5.0,
enter_trade_next_open_period = True,
min_account_balance = 1000.0,
portfRebalanceFreq = PortfolioRebalanceFrequency.Never,
portfRebalancePeriods = 1
)
print("Number of configured Trade Strategies: ", len(portf_registered_obj.taRegisterItems) )
training_period = DatasetDef(datasetType = DatasetType.Training,
strBegDateAIModels = "1993-07-01",
strBegDate = "1994-01-01",
strEndDate = "1998-12-31" )
validation_period = DatasetDef(datasetType = DatasetType.Validation,
strBegDateAIModels = "1998-07-01",
strBegDate = "1999-01-01",
strEndDate = "2000-12-31" )
testing_period = DatasetDef(datasetType = DatasetType.Testing,
strBegDateAIModels = "2000-07-01",
strBegDate = "2001-01-01",
strEndDate = "2001-12-31" )
fit_datasets = FitDatasetsDef( trainingDataset = training_period,
validationDataset = validation_period )
tsExecuteEngine = BacktestExecutionSlideWindowWFA( \
name = "SW-WFA-Backtest 4",
trade_asset_registered_item = portf_registered_obj,
wfa_slide_win_size_list = [ 4, 12 ] , # list of int, associated with wfa_slide_win_period_list
wfa_slide_win_period_list = [ WFASlideWindowPeriod.Months, WFASlideWindowPeriod.Months ],
wfa_sw_scenario_obj = WFASlideWinScenarioSlidingDatasets(\
fit_dataset = fit_datasets,
test_period = testing_period,
slide_win_size = 1,
slide_win_period = WFASlideWindowPeriod.Years,
end_date_last_test_period = datetime(year=2010, month=12, day=31) ),
anchor_fit_dataset = False )
tsExecuteEngine.evaluate()
tsExecuteEngine.getSummaryMetrics().to_excel("SW-WFA-Backtest-4 backtest-metrics.xlsx")
DOW
tsExecuteEngine.getSummaryMetrics()\
[ [ 'wfa_sw_iter_no', 'wfa_slide_win_size', 'wfa_slide_win_period',
'ta_reg_item_name', 'is_portfolio', 'trade_asset', 'order_type',
'enter_num_models', 'enter_model', 'enter_model_type',
'exit_num_models', 'exit_model', 'exit_model_type',
'stop_model', 'stop_model_type',
'Start Period', 'End Period',
'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ].\
query('trade_asset == "^DJI" ')
Nasdaq
tsExecuteEngine.getSummaryMetrics()\
[ [ 'wfa_sw_iter_no', 'wfa_slide_win_size', 'wfa_slide_win_period',
'ta_reg_item_name', 'is_portfolio', 'trade_asset', 'order_type',
'enter_num_models', 'enter_model', 'enter_model_type',
'exit_num_models', 'exit_model', 'exit_model_type',
'stop_model', 'stop_model_type',
'Start Period', 'End Period',
'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ].\
query('trade_asset == "^IXIC" ')
S&P 500
tsExecuteEngine.getSummaryMetrics()\
[ [ 'wfa_sw_iter_no', 'wfa_slide_win_size', 'wfa_slide_win_period',
'ta_reg_item_name', 'is_portfolio', 'trade_asset', 'order_type',
'enter_num_models', 'enter_model', 'enter_model_type',
'exit_num_models', 'exit_model', 'exit_model_type',
'stop_model', 'stop_model_type',
'Start Period', 'End Period',
'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ].\
query('trade_asset == "^GSPC" ')
Portfolio K: Long and Multiple Configured SMA Trade Strategies for US Indixes, with Stop Models
Description:
1. Seven distinct SMA Trade Strategies for enter/exit a trade, plus an ensemble trade strategy
of all seven SMA models
2. Eight different stop-models
1. Stop Loss order with specified stop-loss percent limit
2. Trail Stop Loss order with specified trail-stop-loss percent limit
3. Combine Stop-Loss & Trail-Stop-Loss order with specified percent limits
4-8. Five different Combine Stop-Loss & Trail-Stop-Loss models, configured with dynamic derived
stop-loss and trail-stop-loss percent limits using Average True Range(ATR) algorithm
3. $2,000,000/strategy
3. No-Rebalance during the backtest
4. 100% capital invested
5. Portfolio investment using equal weights for each trade strategy
Backtest:
1. Type: regular
2. Test Period:
1. Begin Date = 2001-01-01
2. End Date = 2020-12-31
portfolio_trade_assets = [ "^DJI", "^IXIC", "^GSPC" ]
dirPathMarketData = '../Data/US_Market_Indixes'
supportedTradeAssets = [ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
beg_date_str = "1980-01-01"
end_date_str = None
ts_marketdat_mng = TradeStrategyMarketDataMng(\
marketDataProviderName = "yahoofinance",
supportedTradeAssets = supportedTradeAssets,
stock_price_col_name = "Adj Close",
fileNameMarketData = "US_Indixes_And_ETFs_MrkData_From_1980",
dirPathMarketData = dirPathMarketData,
beg_date_str = beg_date_str,
end_date_str = end_date_str,
forceCreateMarketData = False,
interval = "1d" )
brokerTradingObj = SimBrokerTrading()
tsConfDat = TradeStrategyConfigData()
# Set Config
tsConfDat.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "entry" : { 'votingPolicy' : 1, 'incNoInvestInVotingDec' : False,
'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
'lastn_match' : 1, 'cross_over_signal_for_trading' : False },
"exit" : { 'votingPolicy' : 1,
'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
'lastn_match' : 1 }
}
} )
# TS #1
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_1",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 20, 'win_slow' : 100 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #2
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_2",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 10, 'win_slow' : 50 } ,
'entry_policy_args' : { 'lastn_match' : 2, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #3
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_3",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 10, 'win_slow' : 57 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #4
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_4",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 15, 'win_slow' : 60 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #5
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_5",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 15, 'win_slow' : 75 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #6
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_6",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 7, 'win_slow' : 35 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #7
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_7",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 12, 'win_slow' : 40 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# ***
# *** Configure Several Types of Stop Actions
# ***
# order_type = 1 ( Stop-Loss )
# order_type = 2 ( Trail-Stop-Loss )
# order_type = 3 ( Combine Stop-Loss & Trail-Stop-Loss )
#
# Stop Models :
# fixval { user-defined stop-loss-percent and/or trail-stop-loss-percent }
# atr { uses ATR model to dynamically determined the stop and trail stop loss percents }
# 1) *** Stop-Loss Order Type
tsStopsConfDat_Stop_Loss = TradeStrategyConfigData()
tsStopsConfDat_Stop_Loss.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "stop" : { 'order_type' : 1 } }
} )
tsStopsConfDat_Stop_Loss.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "sl_fixval",
'actions_conf' : { "stop" :
{ 'model' : "fixval",
'type' : "ta",
'obj_args' : { 'stop_loss_per' : 0.002, 'trail_stop_loss_per' : 0.005 },
},
},
} )
# 2) *** Trail-Stop-Loss Order Type
tsStopsConfDat_Trail_Stop_Loss = TradeStrategyConfigData()
tsStopsConfDat_Trail_Stop_Loss.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "stop" : { 'order_type' : 2} }
} )
tsStopsConfDat_Trail_Stop_Loss.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "tsl_fixval",
'actions_conf' : { "stop" :
{ 'model' : "fixval",
'type' : "ta",
'obj_args' : { 'stop_loss_per' : 0.002, 'trail_stop_loss_per' : 0.005 },
},
},
} )
# 3) *** Combine Stop-Loss & Trail-Stop-Loss Order Type - Using Fixed Values
tsStopsConfDat_Stop_Loss_And_Trail_SL_1 = TradeStrategyConfigData()
tsStopsConfDat_Stop_Loss_And_Trail_SL_1.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "stop" : { 'order_type' : 3 } }
} )
tsStopsConfDat_Stop_Loss_And_Trail_SL_1.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "sl_tsl_fixval",
'actions_conf' : { "stop" :
{ 'model' : "fixval",
'type' : "ta",
'obj_args' : { 'stop_loss_per' : 0.002, 'trail_stop_loss_per' : 0.005 },
},
},
} )
# 4) *** Combine Stop-Loss & Trail-Stop-Loss Order Type - Using Dynamic Values from ATR
tsStopsConfDat_Stop_Loss_And_Trail_SL_2 = TradeStrategyConfigData()
tsStopsConfDat_Stop_Loss_And_Trail_SL_2.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "stop" : { 'order_type' : 3 } }
} )
tsStopsConfDat_Stop_Loss_And_Trail_SL_2.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "sl_tsl_atr_1",
'actions_conf' : { "stop" :
{ 'model' : "atr",
'type' : "ta",
'obj_args' : { 'atr_mov_ave' : 14,
'stop_loss_mult' : 0.5,
'trail_stop_loss_mult' : 1.0,
'max_stop_loss_per' : 0.05,
'min_stop_loss_per' : 0.002,
'max_trail_stop_loss_per' : 0.05,
'min_trail_stop_loss_per' : 0.005,
},
},
},
} )
# 5) ***
tsStopsConfDat_Stop_Loss_And_Trail_SL_3 = TradeStrategyConfigData()
tsStopsConfDat_Stop_Loss_And_Trail_SL_3.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "stop" : { 'order_type' : 3 } }
} )
tsStopsConfDat_Stop_Loss_And_Trail_SL_3.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "sl_tsl_atr_2",
'actions_conf' : { "stop" :
{ 'model' : "atr",
'type' : "ta",
'obj_args' : { 'atr_mov_ave' : 7,
'stop_loss_mult' : 0.05,
'trail_stop_loss_mult' : 0.075,
},
},
},
} )
# 6) ***
tsStopsConfDat_Stop_Loss_And_Trail_SL_4 = TradeStrategyConfigData()
tsStopsConfDat_Stop_Loss_And_Trail_SL_4.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "stop" : { 'order_type' : 3 } }
} )
tsStopsConfDat_Stop_Loss_And_Trail_SL_4.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "sl_tsl_atr_3",
'actions_conf' : { "stop" :
{ 'model' : "atr",
'type' : "ta",
'obj_args' : { 'atr_mov_ave' : 7,
'stop_loss_mult' : 0.01,
'trail_stop_loss_mult' : 0.03,
},
},
},
} )
# 7) ***
tsStopsConfDat_Stop_Loss_And_Trail_SL_5 = TradeStrategyConfigData()
tsStopsConfDat_Stop_Loss_And_Trail_SL_5.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "stop" : { 'order_type' : 3 } }
} )
tsStopsConfDat_Stop_Loss_And_Trail_SL_5.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "sl_tsl_atr_4",
'actions_conf' : { "stop" :
{ 'model' : "atr",
'type' : "ta",
'obj_args' : { 'atr_mov_ave' : 7,
'stop_loss_mult' : 0.05,
'trail_stop_loss_mult' : 0.075,
'max_stop_loss_per' : 0.005,
'min_stop_loss_per' : 0.002,
'max_trail_stop_loss_per' : 0.005,
'min_trail_stop_loss_per' : 0.002,
},
},
},
} )
# 8) ***
tsStopsConfDat_Stop_Loss_And_Trail_SL_6 = TradeStrategyConfigData()
tsStopsConfDat_Stop_Loss_And_Trail_SL_6.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "stop" : { 'order_type' : 3 } }
} )
tsStopsConfDat_Stop_Loss_And_Trail_SL_6.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "sl_tsl_atr_5",
'actions_conf' : { "stop" :
{ 'model' : "atr",
'type' : "ta",
'obj_args' : { 'atr_mov_ave' : 7,
'stop_loss_mult' : 0.05,
'trail_stop_loss_mult' : 0.075,
'max_stop_loss_per' : 0.005,
'min_stop_loss_per' : 0.002,
'max_trail_stop_loss_per' : 0.01,
'min_trail_stop_loss_per' : 0.005,
},
},
},
} )
stopsConfDatList = [ tsStopsConfDat_Stop_Loss, tsStopsConfDat_Trail_Stop_Loss,
tsStopsConfDat_Stop_Loss_And_Trail_SL_1, tsStopsConfDat_Stop_Loss_And_Trail_SL_2,
tsStopsConfDat_Stop_Loss_And_Trail_SL_3, tsStopsConfDat_Stop_Loss_And_Trail_SL_4,
tsStopsConfDat_Stop_Loss_And_Trail_SL_5, tsStopsConfDat_Stop_Loss_And_Trail_SL_6
]
taRegItemGen = TradeAssetRegisterItemGenerator()
portf_registered_obj = taRegItemGen.createTARegItem(
name_ta_reg_item = "SW-WFA-Backtest 5",
# *** Trade Assets & Market Data
portfolio_trade_assets = portfolio_trade_assets,
ts_marketdat_mng = ts_marketdat_mng,
dirPathMarketData = dirPathMarketData,
market_data_period = MarketDataPeriod.Day,
# *** Broker
brokerTradingObj = brokerTradingObj,
# *** T.S. Permutations for each of the following sets of models
enter_exit_config_models = tsConfDat,
stop_config_models = stopsConfDatList,
# *** Investment Manager Params
minPeriodsBetweenTrades = 1,
initInvestmentPerTradeStrategy = 2000000.0,
capPercentToInvestPerTrade = 100.0,
minInvestPercent = 5.0,
enter_trade_next_open_period = True,
min_account_balance = 1000.0,
portfRebalanceFreq = PortfolioRebalanceFrequency.Never,
portfRebalancePeriods = 1
)
print("Number of configured Trade Strategies: ", len(portf_registered_obj.taRegisterItems) )
training_period = DatasetDef(datasetType = DatasetType.Training,
strBegDateAIModels = "1997-07-01",
strBegDate = "1998-01-01",
strEndDate = "1999-12-31" )
validation_period = DatasetDef(datasetType = DatasetType.Validation,
strBegDateAIModels = "1999-07-01",
strBegDate = "2000-01-01",
strEndDate = "2000-12-31" )
testing_period = DatasetDef(datasetType = DatasetType.Testing,
strBegDateAIModels = "2000-07-01",
strBegDate = "2001-01-01",
strEndDate = "2001-12-31" )
fit_datasets = FitDatasetsDef( trainingDataset = training_period,
validationDataset = validation_period )
tsExecuteEngine_sw = BacktestExecutionSlideWindowWFA( \
name = "SW-WFA-Backtest 5",
trade_asset_registered_item = portf_registered_obj,
wfa_slide_win_size_list = [ 20 ] , # No use here, no AI Strategies, just TA ones
wfa_slide_win_period_list = [ WFASlideWindowPeriod.Months ],
wfa_sw_scenario_obj = WFASlideWinScenarioSlidingDatasets(\
fit_dataset = fit_datasets, # no use in this backtest
test_period = testing_period,
slide_win_size = 1,
slide_win_period = WFASlideWindowPeriod.Years,
end_date_last_test_period = datetime(year=2020, month=12, day=31) ),
anchor_fit_dataset = False )
tsExecuteEngine_sw.evaluate()
tsExecuteEngine_sw.getSummaryMetrics().to_excel("SW-WFA-Backtest-5 backtest-metrics.xlsx")
DOW
tsExecuteEngine_sw.getSummaryMetrics()\
[ [ 'wfa_sw_iter_no', 'wfa_slide_win_size', 'wfa_slide_win_period',
'ta_reg_item_name', 'is_portfolio', 'trade_asset', 'order_type',
'enter_num_models', 'enter_model', 'enter_model_type',
'exit_num_models', 'exit_model', 'exit_model_type',
'stop_model', 'stop_model_type',
'Start Period', 'End Period',
'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ].\
query('trade_asset == "^DJI" ')
Nasdaq
tsExecuteEngine_sw.getSummaryMetrics()\
[ [ 'wfa_sw_iter_no', 'wfa_slide_win_size', 'wfa_slide_win_period',
'ta_reg_item_name', 'is_portfolio', 'trade_asset', 'order_type',
'enter_num_models', 'enter_model', 'enter_model_type',
'exit_num_models', 'exit_model', 'exit_model_type',
'stop_model', 'stop_model_type',
'Start Period', 'End Period',
'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ].\
query('trade_asset == "^IXIC" ')
S&P 500
tsExecuteEngine_sw.getSummaryMetrics()\
[ [ 'wfa_sw_iter_no', 'wfa_slide_win_size', 'wfa_slide_win_period',
'ta_reg_item_name', 'is_portfolio', 'trade_asset', 'order_type',
'enter_num_models', 'enter_model', 'enter_model_type',
'exit_num_models', 'exit_model', 'exit_model_type',
'stop_model', 'stop_model_type',
'Start Period', 'End Period',
'Cumulative Return ', 'CAGR%', 'Sharpe', 'Max Drawdown ', 'Best Day ', 'Worst Day '] ].\
query('trade_asset == "^GSPC" ')
The reports currently supported are provided by quantstats, https://github.com/ranaroussi/quantstats.
from trade_engine.reports.BacktestReports import BacktestReports
Description:
Backtest:
1. Type: WFA Backtest
2. AI Models Fit Date Ranges
1. Training Period:
1. Begin Date = 2008-05-01
2. End Date = 2010-04-30
2. Validation Period:
1. Begin Date = 2010-05-01
2. End Date = 2010-12-31
4. Test Period:
1. Begin Date = 2011-01-01
2. End Date = 2012-12-31
portfolio_trade_assets = [ "^DJI", "^IXIC", "^GSPC" ]
dirPathMarketData = '../Data/US_Market_Indixes'
supportedTradeAssets = [ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
beg_date_str = "1980-01-01"
end_date_str = None
ts_marketdat_mng = TradeStrategyMarketDataMng(\
marketDataProviderName = "yahoofinance",
supportedTradeAssets = supportedTradeAssets,
stock_price_col_name = "Adj Close",
fileNameMarketData = "US_Indixes_And_ETFs_MrkData_From_1980",
dirPathMarketData = dirPathMarketData,
beg_date_str = beg_date_str,
end_date_str = end_date_str,
forceCreateMarketData = False,
interval = "1d" )
brokerTradingObj = SimBrokerTrading()
tsConfDat = TradeStrategyConfigData()
# Set Config
tsConfDat.tsSetConfig(\
ts_set_conf_dict =
{ 'set_actions_conf' :
{ "entry" : { 'votingPolicy' : 1, 'incNoInvestInVotingDec' : False,
'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
'lastn_match' : 1, 'cross_over_signal_for_trading' : False },
"exit" : { 'votingPolicy' : 1,
'minPerVotingLong' : 0.0, 'minPerVotingShort' : 0.0,
'lastn_match' : 1 }
}
} )
# TS #1
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_gru_1",
'actions_conf' : { "entry_exit" :
{ 'model' : "gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 } },
},
} )
# TS #2
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_lstm",
'actions_conf' : { "entry_exit" :
{ 'model' : "lstm",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #3
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_conv1d_gru",
'actions_conf' : { "entry_exit" :
{ 'model' : "conv1d_gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 50, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 5,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #8
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_gru_2",
'actions_conf' : { "entry_exit" :
{ 'model' : "gru",
'type' : "ai",
'obj_args' : { 'n_steps' : 40, 'no_neurons_lay1' : 20,
'no_neurons_lay2' : 20, 'pred_ahead_periods' : 3,
'ext_trade_dyn' : True, 're_eval_exit_dyn' : True,
'epochs' : 20 }
}
} } )
# TS #10
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma_2",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 15, 'win_slow' : 60 } ,
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #16
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_kama",
'actions_conf' : { "entry_exit" :
{ 'model' : "kama",
'type' : "ta",
'obj_args' : { 'window_fast' : 10, 'pow1_fast' : 2, 'pow2_fast' : 30,
'window_slow' : 10, 'pow1_slow' : 5, 'pow2_slow' : 30 },
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
# TS #17
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_tsi",
'actions_conf' : { "entry_exit" :
{ 'model' : "tsi",
'type' : "ta",
'obj_args' : { 'window_slow' : 25, 'window_fast' : 5 },
'entry_policy_args' : { 'lastn_match' : 1, 'cross_enter_signal' : False },
'exit_policy_args' : { 'lastn_match' : 1 },
},
} } )
taRegItemGen = TradeAssetRegisterItemGenerator()
portf_registered_obj = taRegItemGen.createTARegItem(
name_ta_reg_item = "Portfolio For Reports",
# *** Trade Assets & Market Data
portfolio_trade_assets = portfolio_trade_assets,
ts_marketdat_mng = ts_marketdat_mng,
dirPathMarketData = dirPathMarketData,
market_data_period = MarketDataPeriod.Day,
# *** Broker
brokerTradingObj = brokerTradingObj,
# *** T.S. Permutations for each of the following sets of models
enter_exit_config_models = tsConfDat,
# *** Investment Manager Params
minPeriodsBetweenTrades = 1,
initInvestmentPerTradeStrategy = 2000000.0,
capPercentToInvestPerTrade = 100.0,
minInvestPercent = 5.0,
enter_trade_next_open_period = True,
min_account_balance = 1000.0,
portfRebalanceFreq = PortfolioRebalanceFrequency.Never,
portfRebalancePeriods = 1
)
training_period = DatasetDef(datasetType = DatasetType.Training,
strBegDateAIModels = "2007-11-01",
strBegDate = "2008-05-01",
strEndDate = "2010-04-30" )
validation_period = DatasetDef(datasetType = DatasetType.Validation,
strBegDateAIModels = "2009-11-01",
strBegDate = "2010-05-01",
strEndDate = "2010-12-31" )
testing_period = DatasetDef(datasetType = DatasetType.Testing,
strBegDateAIModels = "2010-07-01",
strBegDate = "2011-01-01",
strEndDate = "2012-12-31" )
fit_datasets = FitDatasetsDef( trainingDataset = training_period,
validationDataset = validation_period )
tsExecuteEngine = BacktestExecutionWFA( \
name = "WFA Backtest for Reports",
test_period = testing_period,
fit_datasets_start = fit_datasets,
trade_asset_registered_item = portf_registered_obj,
wfa_slide_win_size = 4,
wfa_slide_win_period = WFASlideWindowPeriod.Months,
anchor_fit_dataset = False )
tsExecuteEngine.evaluate()
tsExecuteEngine.getExecutionMetrics().query('Is_Portfolio == "Yes"')
DOW Jones
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']].\
query('TA_Reg_Name.str.contains("DJI")', engine='python')
Nasdaq
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']].\
query('TA_Reg_Name.str.contains("IXIC")', engine='python')
S&P 500
tsExecuteEngine.getExecutionMetrics()[ ['TA_Reg_Name', 'Is_Portfolio', 'Num_Trades_Completed',
'Init_Capital', 'Final_Capital', 'Cum_Return', 'Backtest_Status']].\
query('TA_Reg_Name.str.contains("GSPC")', engine='python')
BacktestReports.createTearsheetReport(\
backtest = tsExecuteEngine,
ta_reg_item_name = "all_All_^IXIC",
ta_reg_item_benchmark_name = "Long-Only Trade Strategy for ^IXIC ", # optional
report_type = "full" )
BacktestReports.createTearsheetReport(\
backtest = tsExecuteEngine,
ta_reg_item_name = "all_All_^DJI",
ta_reg_item_benchmark_name = "Long-Only Trade Strategy for ^DJI ", # optional
report_type = "full" )
BacktestReports.createTearsheetReport(\
backtest = tsExecuteEngine,
ta_reg_item_name = "Portfolio For Reports",
ta_reg_item_benchmark_name = None, # optional
report_type = "full" )
BacktestReports.createHTMLTearsheetReport(\
backtest = tsExecuteEngine,
ta_reg_item_name = "all_All_^IXIC",
ta_reg_item_benchmark_name = "Long-Only Trade Strategy for ^IXIC ", # optional
title = 'Strategy Tearsheet',
download_filename = 'ts-tearsheet.html' )
Description:
1. $2.0M Budget
2. 100% capital invested
3. Apply 1% fit per trade transaction
Trade Strategies:
1. One trade strategy: Nasdaq using Simple Moving Average(SMA) for entering/exiting a trade
Backtest:
1. Type: regular
2. Test Period:
1. Begin Date = 2001-01-01
2. End Date = 2005-12-31
trade_assets = [ "^IXIC" ]
dirPathMarketData = '../Data/US_Market_Indixes'
supportedTradeAssets = [ "^DJI", "^IXIC", "^GSPC", "UDOW", "SDOW", "SPXL", "SPXS", "TQQQ", "SQQQ" ]
beg_date_str = "2000-01-01"
end_date_str = None
ts_marketdat_mng = TradeStrategyMarketDataMng(\
marketDataProviderName = "yahoofinance",
supportedTradeAssets = supportedTradeAssets,
stock_price_col_name = "Adj Close",
fileNameMarketData = "US_Indixes_And_ETFs_MrkData",
dirPathMarketData = dirPathMarketData,
beg_date_str = beg_date_str,
end_date_str = end_date_str,
forceCreateMarketData = False,
interval = "1d" )
brokerTradingObj = SimBrokerTrading()
tsConfDat = TradeStrategyConfigData()
# SMA JSON Configuration
#
# Model Configuration:
# win_fast : fast moving average
# win_slow : slow moving average
# Signals to enter and exit a trade based on the fast ma crossing the slow ma
tsConfDat.addTSConf(\
ts_conf_dict = {
'ts_unique_tag' : "ts_sma",
'actions_conf' : { "entry_exit" :
{ 'model' : "sma",
'type' : "ta",
'obj_args' : { 'win_fast' : 20, 'win_slow' : 100 } },
} } )
taRegItemGen = TradeAssetRegisterItemGenerator()
portf_registered_obj = taRegItemGen.createTARegItem(
name_ta_reg_item = "Portfolio Test Fee Policy",
# *** Trade Assets & Market Data
portfolio_trade_assets = portfolio_trade_assets,
ts_marketdat_mng = ts_marketdat_mng,
dirPathMarketData = dirPathMarketData,
market_data_period = MarketDataPeriod.Day,
# *** Broker
brokerTradingObj = brokerTradingObj,
# *** T.S. Permutations for each of the following sets of models
enter_exit_config_models = tsConfDat,
# *** Investment Manager Params
minPeriodsBetweenTrades = 1,
initInvestmentPerTradeStrategy = 2000000.0,
capPercentToInvestPerTrade = 100.0,
minInvestPercent = 5.0,
enter_trade_next_open_period = True,
min_account_balance = 1000.0,
portfRebalanceFreq = PortfolioRebalanceFrequency.Never,
portfRebalancePeriods = 1,
# *** Fee Policy Params per Trade
tradeFeeType = TradeFeeType.FixPercentPerTransactionValue,
percentPerTransaction = 0.01 # 1% per trade
)
tsExecuteEngine = BacktestExecution( \
name = "Backtest for Testing Trade Fee Policy - flat fee per transaction",
timePeriod = DatasetDef(datasetType = DatasetType.Testing,
strBegDate = "2001-01-01",
strEndDate = "2005-12-31" ),
trade_asset_registered_item = portf_registered_obj )
tsExecuteEngine.evaluate()
tsExecuteEngine.getExecutionMetrics()